如何将pandas数据框中每个组的多列值合并为一组的python方式是什么?

2024-07-05 14:59:58 发布

您现在位置:Python中文网/ 问答频道 /正文

给定一个数据帧,将列的每个组的值折叠为一个集合非常简单:

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列的表,并且我想以一种python的方式来实现它,那会怎么样?”你知道吗

目前我有一个解决方案,但我不认为这是最好的方法:

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)

提前谢谢!你知道吗


Tags: 数据df方式pythonicpdbobgroupbyset
2条回答
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}

这里有一个collections.defaultdict方法。Pythonic是主观的。你知道吗

这个解决方案肯定不是泛化的。当将groupby.agglambda一起使用时,数据帧通常会有很大的开销,因此您可能会发现下面的解决方案更有效。你知道吗

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}

相关问题 更多 >