Pandas:如何计算按 ID 分组的分类特征的出现次数

Sin*_*ico 5 python numpy pandas

假设我有这个 DataFramedf

My_ID   My_CAT
  1       A
  2       B  
  3       C
  1       A  
  1       B 
  2       D 
Run Code Online (Sandbox Code Playgroud)

我想知道每个不同的My_Cat值出现了多少次My_ID

我需要它以密集数组的形式,例如

My_ID   A    B    C   D
  1     2    1    0   0
  2     0    1    0   1
  3     0    0    1   0
Run Code Online (Sandbox Code Playgroud)

我尝试过

df.groupby(['My_ID','My_CAT']).count()
Run Code Online (Sandbox Code Playgroud)

但尽管我看到数据根据我的需要进行分组,但发生的次数并未被计算在内。

jez*_*ael 5

使用crosstab(更少打字,最慢):

df = pd.crosstab(df['My_ID'], df['My_CAT'])
print (df)
My_CAT  A  B  C  D
My_ID             
1       2  1  0  0
2       0  1  0  1
3       0  0  1  0
Run Code Online (Sandbox Code Playgroud)

使用groupby+ 聚合size+更快的解决方案unstack

df = df.groupby(['My_ID','My_CAT']).size().unstack(fill_value=0)
print (df)
My_CAT  A  B  C  D
My_ID             
1       2  1  0  0
2       0  1  0  1
3       0  0  1  0
Run Code Online (Sandbox Code Playgroud)

最后:

df = df.reset_index().rename_axis(None, axis=1)
print (df)
   My_ID  A  B  C  D
0      1  2  1  0  0
1      2  0  1  0  1
2      3  0  0  1  0
Run Code Online (Sandbox Code Playgroud)

注意:

大熊猫的大小和数量有什么区别?

时间(更大的数据):

np.random.seed(123)
N = 100000
L = list('abcdefghijklmno')
df = pd.DataFrame({'My_CAT': np.random.choice(L, N),
                   'My_ID':np.random.randint(1000,size=N)})
print (df)

In [79]: %timeit pd.crosstab(df['My_ID'], df['My_CAT'])
10 loops, best of 3: 96.7 ms per loop

In [80]: %timeit df.groupby(['My_ID','My_CAT']).size().unstack(fill_value=0)
100 loops, best of 3: 14.2 ms per loop

In [81]: %timeit pd.get_dummies(df.My_CAT).groupby(df.My_ID).sum()
10 loops, best of 3: 25.5 ms per loop

In [82]: %timeit df.groupby('My_ID').My_CAT.value_counts().unstack(fill_value=0)
10 loops, best of 3: 25.4 ms per loop

In [136]: %timeit xtab_df(df, 'My_ID', 'My_CAT')
100 loops, best of 3: 4.23 ms per loop

In [137]: %timeit xtab(df, 'My_ID', 'My_CAT')
100 loops, best of 3: 4.61 ms per loop
Run Code Online (Sandbox Code Playgroud)