2

我有一个这样的pandas数据框df,说

ID activity date
1  A        4
1  B        8
1  A        12
1  C        12
2  B        9
2  A        10
3  A        3
3  D        4

我想返回一个表格,计算一些activity在精确列表中出现的次数,比如l = [A, B]在这种情况下,然后

ID activity(count)_A  activity(count)_B
1  2                  1
2  1                  2
3  1                  0

是我需要的。

执行此操作的最快方法是什么?理想情况下没有for循环

谢谢 !

编辑:我知道有pivot做这种工作的功能。但就我而言,我的activity类型比我真正需要在列表中计算的类型要多得多l。它仍然是最佳使用pivot吗?

4

3 回答 3

1

您可以使用isinwithboolean indexing作为第一步,然后使用 pivoting-fastest should be和groupby,然后和最后,使用真实数据对每个解决方案进行最佳测试:sizeunstackpivot_tablecrosstab

df2 = (df[df['activity'].isin(['A','B'])]
         .groupby(['ID','activity'])
         .size()
         .unstack(fill_value=0)
         .add_prefix('activity(count)_')
         .reset_index()
         .rename_axis(None, axis=1))

print (df2)
   ID  activity(count)_A  activity(count)_B
0   1                  2                  1
1   2                  1                  1
2   3                  1                  0

或者:

df1 = df[df['activity'].isin(['A','B'])]

df2 = (pd.crosstab(df1['ID'], df1['activity'])
        .add_prefix('activity(count)_')
        .reset_index()
        .rename_axis(None, axis=1))

或者:

df2 = (df[df['activity'].isin(['A','B'])]
          .pivot_table(index='ID', columns='activity', aggfunc='size', fill_value=0)
          .add_prefix('activity(count)_')
          .reset_index()
          .rename_axis(None, axis=1))
于 2018-08-01T16:30:43.820 回答
0

我相信df.groupby('activity').size().reset_index(name='count') 应该如你所愿。

于 2018-08-01T16:38:14.193 回答
0

只需聚合Counter并使用pd.DataFrame默认构造函数

from collections import Counter

agg_= df.groupby(df.index).ID.agg(Counter).tolist()
ndf = pd.DataFrame(agg_)

    A   B   C   D
0   2   1.0 1.0 NaN
1   1   1.0 NaN NaN
2   1   NaN NaN 1.0

如果有l = ['A', 'B'],请过滤

ndf[l]

    A   B   
0   2   1.0 
1   1   1.0 
2   1   NaN
于 2018-08-01T17:14:08.340 回答