问题:通过多个条件合并不同数量的行
以下是数据集如何看起来像的风格示例
"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) ...
它更加紧凑易读。