按组分组以创建新列

4

我想从数据框中创建一个新的数据框,如果索引已经存在,则创建新的列,但我不知道要创建多少个列:

pd.DataFrame([["John","guitar"],["Michael","football"],["Andrew","running"],["John","dancing"],["Andrew","cars"]])

and I want :

pd.DataFrame([["John","guitar","dancing"],["Michael","Football",None],["Andrew","running","cars"]])

在开始的时候,我不知道应该创建多少列。


2
@FFL75 更新了更快的替代方案,更适用于大型数据框。 - yatu
实际上,在我的真实使用情况中,了解值的重复非常大,而且在这个例子中没有说明要显示唯一值 :) - Arli94
3个回答

6
df = pd.DataFrame([["John","guitar"],["Michael","football"],["Andrew","running"],["John","dancing"],["Andrew","cars"]], columns = ['person','hobby'])

你可以按照person进行分组,并在hobby中搜索unique。然后使用.apply(pd.Series)将列表扩展为列:
df.groupby('person').hobby.unique().apply(pd.Series).reset_index()
    person         0        1
0   Andrew   running     cars
1     John    guitar  dancing
2  Michael  football      NaN

如果有一个大的数据框,可以尝试更高效的替代方案:

df = df.groupby('person').hobby.unique()
df = pd.DataFrame(df.values.tolist(), index=df.index).reset_index()

本质上执行的操作是相同的,但避免了在应用pd.Series时循环遍历行。


1
你的回答有什么问题 - 为什么是唯一的?为什么pd.Series非常慢? - jezrael
1
同意.apply(pd.Series)不是处理非常大的数据框的最佳选择,但如果不是这种情况,它将完成工作。 “为什么要唯一” - 我假设OP想要的是记录每个人在数据框中存在哪些爱好。否则,请让我知道@ffl75。 - yatu

1

使用 GroupBy.cumcount 获取 counter,然后通过 unstack 进行重塑:

df1 = pd.DataFrame([["John","guitar"],
                    ["Michael","football"],
                    ["Andrew","running"],
                    ["John","dancing"],
                    ["Andrew","cars"]], columns=['a','b'])

         a         b
0     John    guitar
1  Michael  football
2   Andrew   running
3     John   dancing
4   Andrew      cars


df = (df1.set_index(['a', df1.groupby('a').cumcount()])['b']
         .unstack()
         .rename_axis(-1)
         .reset_index()
         .rename(columns=lambda x: x+1))
print (df)

         0         1        2
0   Andrew   running     cars
1     John    guitar  dancing
2  Michael  football      NaN

或通过构造函数聚合 list 并创建新的字典:

s = df1.groupby('a')['b'].agg(list)
df = pd.DataFrame(s.values.tolist(), index=s.index).reset_index()
print (df)
         a         0        1
0   Andrew   running     cars
1     John    guitar  dancing
2  Michael  football     None

1
@RavinderSingh13 - 谢谢。 - jezrael

0
假设列名为['person', 'activity'],您可以这样做:
df_out = df.groupby('person').agg(list).reset_index()
df_out = pd.concat([df_out, pd.DataFrame(df_out['activity'].values.tolist())], axis=1)
df_out = df_out.drop('activity', 1)

给你

    person         0        1
0   Andrew   running     cars
1     John    guitar  dancing
2  Michael  football     None

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接