![](/img/trans.png)
[英]Python Pandas Count columns with multiple conditions and groupby
[英]Pandas - count if multiple conditions
在python中有一個數據框:
CASE TYPE
1 A
1 A
1 A
2 A
2 B
3 B
3 B
3 B
我如何創建一個結果數據框,將產生所有案例,如果案例僅分配了“ A”,則為“ A”,如果僅分配“ B”則為“ B”,如果案例同時為A和B,則為“ MIXED” ?
結果將是:
Case Type
1 A
2 MIXED
3 B
這是一個選項,我們首先按CASE
組收集TYPE作為列表,然后檢查唯一TYPE的length
,如果它大於1
,則返回MIXED
否則返回TYPE本身:
import pandas as pd
import numpy as np
groups = df.groupby('CASE').agg(lambda g: [g.TYPE.unique()]).
apply(lambda row: np.where(len(row.TYPE) > 1, 'MIXED', row.TYPE[0]), axis = 1)
groups
# CASE
# 1 A
# 2 MIXED
# 3 B
# dtype: object
df['NTYPES'] = df.groupby('CASE').transform(lambda x: x.nunique())
df.loc[df.NTYPES > 1, 'TYPE'] = 'MIXED'
df.groupby('TYPE', as_index=False).first().drop('NTYPES', 1)
TYPE CASE
0 A 1
1 B 3
2 MIXED 2
這有點丑陋,但不是那么慢的解決方案:
In [154]: df
Out[154]:
CASE TYPE
0 1 A
1 1 A
2 1 A
3 2 A
4 2 B
5 3 B
6 3 B
7 3 B
8 4 C
9 4 C
10 4 B
In [155]: %paste
(df.groupby('CASE')['TYPE']
.apply(lambda x: x.head(1) if x.nunique() == 1 else pd.Series(['MIX']))
.reset_index()
.drop('level_1', 1)
)
## -- End pasted text --
Out[155]:
CASE TYPE
0 1 A
1 2 MIX
2 3 B
3 4 MIX
時間:針對80萬行DF:
In [191]: df = pd.concat([df] * 10**5, ignore_index=True)
In [192]: df.shape
Out[192]: (800000, 3)
In [193]: %timeit Psidom(df)
1 loop, best of 3: 235 ms per loop
In [194]: %timeit capitalistpug(df)
1 loop, best of 3: 419 ms per loop
In [195]: %timeit Alberto_Garcia_Raboso(df)
10 loops, best of 3: 112 ms per loop
In [196]: %timeit MaxU(df)
10 loops, best of 3: 80.4 ms per loop
這是一個(經過過度設計的)解決方案,可以避免在組和DataFrame.apply
循環(這些過程很慢,因此,如果您的數據集足夠大,避免它們可能變得很重要)。
import pandas as pd
df = pd.DataFrame({'CASE': [1]*3 + [2]*2 + [3]*3,
'TYPE': ['A']*4 + ['B']*4})
我們按CASE
分組並計算TYPE
的相對頻率為A
或B
:
grouped = df.groupby('CASE')
vc = (grouped['TYPE'].value_counts(normalize=True)
.unstack(level=0)
.fillna(0))
這是vc
樣子
CASE 1 2 3
TYPE
A 1.0 0.5 0.0
B 0.0 0.5 0.0
請注意,所有信息都包含在第一行中。 用pd.cut
將所述行切成垃圾箱可得到所需結果:
tolerance = 1e-10
bins = [-tolerance, tolerance, 1-tolerance, 1+tolerance]
types = pd.cut(vc.loc['A'], bins=bins, labels=['B', 'MIXED', 'A'])
我們得到:
CASE
1 A
2 MIXED
3 B
Name: A, dtype: category
Categories (3, object): [B < MIXED < A]
為了更好地衡量,我們可以重命名types
系列:
types.name = 'TYPE'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.