给定一个数据框,将值折叠到一个列的每个组的集合中是很简单的:
df.groupby('A')['B'].apply(set)
但是如果你想在多个列上进行并且结果在数据帧中,你如何以pythonic方式进行呢?
例如,对于以下数据框:
import pandas as pd
df = pd.DataFrame({'user_id': [1, 2, 3, 4, 1, 2, 3],
'class_type': ['Krav Maga', 'Yoga', 'Ju-jitsu', 'Krav Maga', 'Ju-jitsu','Krav Maga', 'Karate'],
'instructor': ['Bob', 'Alice','Bob', 'Alice','Alice', 'Alice','Bob']})
需要的结果是下面以pythonic方式生成的数据框:
|user_id|class_type |instructor |
|-------|-----------------------|---------------|
| 1 | {Krav Maga, Ju-jitsu} | {Bob, Alice} |
| 2 | {Krav Maga, Yoga} | {Alice} |
| 3 | {Karate, Ju-jitsu} | {Bob} |
| 4 | {Krav Maga} | {Alice} |
这是一个虚拟的例子。这个问题来自于:"如果我有一个包含30列的表格并且我想以pythonic方式实现这一点怎么办?"
目前我有一个解决方案,但我认为这不是最好的方法:
df[['grouped_B', 'grouped_C']] = df.groupby('A')[['B','C']].transform(set)
deduped_and_collapsed_df = df.groupby('A')[['A','grouped_B', 'grouped_C']].head(1)
提前谢谢!
答案 0 :(得分:3)
In [11]: df.groupby('user_id', as_index=False).agg(lambda col: set(col.values.tolist()))
Out[11]:
user_id class_type instructor
0 1 {Krav Maga, Ju-jitsu} {Alice, Bob}
1 2 {Yoga, Krav Maga} {Alice}
2 3 {Ju-jitsu, Karate} {Bob}
3 4 {Krav Maga} {Alice}
来自@jezrael的或更短版本:
In [12]: df.groupby('user_id').agg(lambda x: set(x))
Out[12]:
class_type instructor
user_id
1 {Krav Maga, Ju-jitsu} {Alice, Bob}
2 {Yoga, Krav Maga} {Alice}
3 {Ju-jitsu, Karate} {Bob}
4 {Krav Maga} {Alice}
答案 1 :(得分:0)
这是collections.defaultdict
方法。 Pythonic是主观的。
这个解决方案肯定不是Pandonic / Pandorable。将groupby.agg
与lambda
一起使用时,数据框通常会产生很大的开销,因此您可能会发现以下解决方案更有效。
from collections import defaultdict
d_class, d_instr = defaultdict(set), defaultdict(set)
for row in df.itertuples():
idx, class_type, instructor, user_id = row
d_class[user_id].add(class_type)
d_instr[user_id].add(instructor)
res = pd.DataFrame([d_class, d_instr]).T.rename(columns={0: 'class_type', 1: 'instructor'})
结果:
class_type instructor
1 {Krav Maga, Ju-jitsu} {Bob, Alice}
2 {Krav Maga, Yoga} {Alice}
3 {Ju-jitsu, Karate} {Bob}
4 {Krav Maga} {Alice}