Dataframe Pandas的Groupby值计数

whhtz7ly  于 2023-01-07  发布在  其他
关注(0)|答案(6)|浏览(218)

我有以下 Dataframe :

df = pd.DataFrame([
    (1, 1, 'term1'),
    (1, 2, 'term2'),
    (1, 1, 'term1'),
    (1, 1, 'term2'),
    (2, 2, 'term3'),
    (2, 3, 'term1'),
    (2, 2, 'term1')
], columns=['id', 'group', 'term'])

我想把它按idgroup分组,然后计算这个id,group对中每个项的个数。
所以最后我会得到这样的结果:

我可以用df.iterrows()遍历所有行并创建一个新的 Dataframe 来实现我想要的,但这显然效率低下(如果有用的话,我事先知道所有术语的列表,总共有大约10个)。
看起来我必须先分组,然后再计数值,所以我用df.groupby(['id', 'group']).value_counts()尝试了一下,但没有成功,因为value_counts操作的是groupby系列,而不是 Dataframe 。
不管怎样,我可以不用循环就实现这个吗?

pes8fvy9

pes8fvy91#

我使用groupbysize

df.groupby(['id', 'group', 'term']).size().unstack(fill_value=0)

时间

1,000,000行

df = pd.DataFrame(dict(id=np.random.choice(100, 1000000),
                       group=np.random.choice(20, 1000000),
                       term=np.random.choice(10, 1000000)))

63lcw9qa

63lcw9qa2#

使用pivot_table()方法:

In [22]: df.pivot_table(index=['id','group'], columns='term', aggfunc='size', fill_value=0)
Out[22]:
term      term1  term2  term3
id group
1  1          2      1      0
   2          0      1      0
2  2          1      0      1
   3          1      0      0

700K行DF的时序:

In [24]: df = pd.concat([df] * 10**5, ignore_index=True)

In [25]: df.shape
Out[25]: (700000, 3)

In [3]: %timeit df.groupby(['id', 'group', 'term'])['term'].size().unstack(fill_value=0)
1 loop, best of 3: 226 ms per loop

In [4]: %timeit df.pivot_table(index=['id','group'], columns='term', aggfunc='size', fill_value=0)
1 loop, best of 3: 236 ms per loop

In [5]: %timeit pd.crosstab([df.id, df.group], df.term)
1 loop, best of 3: 355 ms per loop

In [6]: %timeit df.groupby(['id','group','term'])['term'].size().unstack().fillna(0).astype(int)
1 loop, best of 3: 232 ms per loop

In [7]: %timeit df.groupby(['id', 'group', 'term']).size().unstack(fill_value=0)
1 loop, best of 3: 231 ms per loop

7M行DF的时序:

In [9]: df = pd.concat([df] * 10, ignore_index=True)

In [10]: df.shape
Out[10]: (7000000, 3)

In [11]: %timeit df.groupby(['id', 'group', 'term'])['term'].size().unstack(fill_value=0)
1 loop, best of 3: 2.27 s per loop

In [12]: %timeit df.pivot_table(index=['id','group'], columns='term', aggfunc='size', fill_value=0)
1 loop, best of 3: 2.3 s per loop

In [13]: %timeit pd.crosstab([df.id, df.group], df.term)
1 loop, best of 3: 3.37 s per loop

In [14]: %timeit df.groupby(['id','group','term'])['term'].size().unstack().fillna(0).astype(int)
1 loop, best of 3: 2.28 s per loop

In [15]: %timeit df.groupby(['id', 'group', 'term']).size().unstack(fill_value=0)
1 loop, best of 3: 1.89 s per loop
clj7thdc

clj7thdc3#

不要去记住冗长的解决方案,来听听Pandas为你准备的一个吧:

df.groupby(['id', 'group', 'term']).count()
ovfsdjhp

ovfsdjhp4#

您可以使用crosstab

print (pd.crosstab([df.id, df.group], df.term))
term      term1  term2  term3
id group                     
1  1          2      1      0
   2          0      1      0
2  2          1      0      1
   3          1      0      0

groupby的另一个解决方案,聚合size,按unstack整形:

df.groupby(['id', 'group', 'term'])['term'].size().unstack(fill_value=0)

term      term1  term2  term3
id group                     
1  1          2      1      0
   2          0      1      0
2  2          1      0      1
   3          1      0      0
    • 时间**:
df = pd.concat([df]*10000).reset_index(drop=True)

In [48]: %timeit (df.groupby(['id', 'group', 'term']).size().unstack(fill_value=0))
100 loops, best of 3: 12.4 ms per loop

In [49]: %timeit (df.groupby(['id', 'group', 'term'])['term'].size().unstack(fill_value=0))
100 loops, best of 3: 12.2 ms per loop
1tu0hz3e

1tu0hz3e5#

如果你想使用value_counts,你可以在一个给定的系列上使用它,并采取以下措施:

df.groupby(["id", "group"])["term"].value_counts().unstack(fill_value=0)

或者以等效的方式,使用.agg方法:

df.groupby(["id", "group"]).agg({"term": "value_counts"}).unstack(fill_value=0)

另一种选择是直接在DataFrame本身上使用value_counts,而不采用groupby

df.value_counts().unstack(fill_value=0)
9njqaruj

9njqaruj6#

另一种选择:

df.assign(count=1).groupby(['id', 'group','term']).sum().unstack(fill_value=0).xs("count", 1)

term      term1  term2  term3
id group                     
1  1          2      1      0
   2          0      1      0
2  2          1      0      1
   3          1      0      0

相关问题