在python中通过多个条件合并不同数量的行



问题:通过多个条件合并不同数量的行

以下是数据集如何看起来像的风格示例

"index" "connector" "type" "q_text" "a_text" "varx" ...
1        1111      1      aa       NA       xx
2        9999      2      NA       tt       NA
3        1111      2      NA       uu       NA
4        9999      1      bb       NA       yy
5        9999      1      cc       NA       zz

目标:数据集应该如何看起来像

"index" "connector" "type" "type.1" "q_text" "q_text.1" "a_text" "a_text.1 " "varx" "varx.1" ...
1        1111      1       2        aa        NA        NA        uu        xx      NA
2        9999      1       2        bb        NA        NA        tt        yy      NA
3        9999      1       2        cc        NA        NA        tt        zz      NA

逻辑:列"类型";具有值1或2,而多行具有值1

如果在";连接器";然后合并";类型"=2,具有行";类型"=1.(因为"类型"=1的多行在"连接器"中具有相同的值)复制类型为2的相应行和合并在";连接器";并且是";类型"=1

我的结果:并非所有结果都被合并,因为";类型"=1与"1"的UNIQUE行相关联;类型"=2

大多数类似的问题都是用SQL来回答的,我在这里无法使用。

df2 = df.copy()
df.index.astype(str)
df2.index.astype(str)
pd.merge(df,df2, how='left', on='connector',right_index=True, left_index=True)
df3 = pd.merge(df.set_index('connector'),df2.set_index('connector'), right_index=True, left_index=True).reset_index()
dfNew = df.merge(df2, how='left', left_on=['connector'], right_on = ['connector'])

我能通过goupby()实现我的目标吗?

解决方案由@victor__von__doom 提供

if __name__ == '__main__':
df = df.groupby('connector', sort=True).apply(lambda c: list(zip(*c.values[:,2:].tolist()))).reset_index(name='merged')
df[['here', 'are', 'all', 'columns', 'except', 'for', 'the', 'connector', 'column']]  = pd.DataFrame(df.merged.tolist())
df = df.drop(['merged'], axis=1)

首先,在合并行时,将新列连接到原始DataFrame上确实很麻烦,尤其是在列数很大的情况下。此外,如果最终为1个连接器值合并3行,为另一个值合并4行(例如),则包含所有值的唯一方法是为某些行创建空列,这从来都不是一个好主意。相反,我已经将合并后的行组合成元组,然后可以有效地解析元组,同时保持DataFrame的大小可控:

import numpy as np
import pandas as pd
if __name__ == '__main__':
data = np.array([[1,2,3,4,5], [1111,9999,1111,9999,9999],
[1,2,2,1,1], ['aa', 'NA', 'NA', 'bb', 'cc'],
['NA', 'tt', 'uu', 'NA', 'NA'],
['xx', 'NA', 'NA', 'yy', 'zz']])
df = pd.DataFrame(data.T, columns = ["index", "connector",
"type", "q_text", "a_text", "varx"])
df = df.groupby("connector", sort=True).apply(lambda c: list(zip(*c.values[:,2:].tolist()))).reset_index(name='merged')
df[["type", "q_text", "a_text", "varx"]]  = pd.DataFrame(df.merged.tolist())
df = df.drop(['merged'], axis=1)

最后的DataFrame看起来像:

connector       type        q_text        a_text          varx ...
0      1111     (1, 2)      (aa, NA)      (NA, uu)      (xx, NA) ...
1      9999  (2, 1, 1)  (NA, bb, cc)  (tt, NA, NA)  (NA, yy, zz) ...

它更加紧凑易读。

最新更新