我有一个有 7 列的表,其中每隔几行就有 6 列保持不变,只有第 7 列发生变化。我想将所有这些行合并为一行,并将第 7 列的值合并为一个列表。
所以如果我有这个数据框:
A B C
0 a 1 2
1 b 3 4
2 c 5 6
3 c 7 6
我想把它转换成这样:
A B C
0 a 1 2
1 b 3 4
2 c [5, 7] 6
由于第 2 行和第 3 行中 A 列和 C 列的值相同,因此它们将折叠成一行,并且 B 列的值将合并到一个列表中。
熔化、爆炸、旋转似乎没有这样的功能。如何使用 Pandas 实现这一目标?
GroupBy.agg
与自定义 lambda 函数一起使用,最后添加 DataFrame.reindex
以获得与原始列相同的顺序:
f = lambda x: x.tolist() if len(x) > 1 else x
df = df.groupby(['A','C'])['B'].agg(f).reset_index().reindex(df.columns, axis=1)
您还可以动态创建列名称,例如:
changes = ['B']
cols = df.columns.difference(changes).tolist()
f = lambda x: x.tolist() if len(x) > 1 else x
df = df.groupby(cols)[changes].agg(f).reset_index().reindex(df.columns, axis=1)
print (df)
A B C
0 a 1 2
1 b 3 4
2 c [5, 7] 6
对于列中的所有列表,解决方案更简单:
changes = ['B']
cols = df.columns.difference(changes).tolist()
df = df.groupby(cols)[changes].agg(list).reset_index().reindex(df.columns, axis=1)
print (df)
A B C
0 a [1] 2
1 b [3] 4
2 c [5, 7] 6
pivot_table
和 applymap
的方法:
(df.pivot_table(index='A',aggfunc=list).applymap(lambda x: x[0] if len(set(x))==1 else x)
.reset_index())
A B C
0 a 1 2
1 b 3 4
2 c [5, 7] 6