数据帧上的 Groupby 值计数 pandas
Groupby value counts on the dataframe pandas
我有以下数据框:
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'])
我想按 id
和 group
对其进行分组,并计算此 id,组对的每个术语的数量。
所以最后我会得到这样的东西:
我能够通过使用 df.iterrows()
遍历所有行并创建一个新的数据框来实现我想要的,但这显然效率低下。 (如果有帮助,我事先知道所有术语的列表,其中约有 10 个)。
看起来我必须按值分组然后计算值,所以我用 df.groupby(['id', 'group']).value_counts()
尝试了它,但它不起作用,因为 value_counts 在 groupby 系列而不是数据帧上运行。
无论如何我可以不用循环实现这个?
您可以使用 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
with aggregating size
, reshaping by 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
使用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
针对 70 万行 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
针对 700 万行 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
我用groupby
和size
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)))
与其记住冗长的解决方案,不如记住 pandas 为您内置的解决方案:
df.groupby(['id', 'group', 'term']).count()
如果你想使用 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)
我有以下数据框:
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'])
我想按 id
和 group
对其进行分组,并计算此 id,组对的每个术语的数量。
所以最后我会得到这样的东西:
我能够通过使用 df.iterrows()
遍历所有行并创建一个新的数据框来实现我想要的,但这显然效率低下。 (如果有帮助,我事先知道所有术语的列表,其中约有 10 个)。
看起来我必须按值分组然后计算值,所以我用 df.groupby(['id', 'group']).value_counts()
尝试了它,但它不起作用,因为 value_counts 在 groupby 系列而不是数据帧上运行。
无论如何我可以不用循环实现这个?
您可以使用 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
with aggregating size
, reshaping by 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
使用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
针对 70 万行 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
针对 700 万行 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
我用groupby
和size
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)))
与其记住冗长的解决方案,不如记住 pandas 为您内置的解决方案:
df.groupby(['id', 'group', 'term']).count()
如果你想使用 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)