如何按 ID 分组并获取每个类别的计数

How to group by ID and get the count per each category

我又来了

我有一个这样的df

    id  c1  c2  c3
0   0   11  12  0
1   0   15  15  1
2   0   4   24  2
3   0   5   13  2
4   0   3   15  1
5   0   5   7   0
6   0   3   18  2
7   0   17  9   3
8   0   0   17  1
9   0   12  0   0
10  1   17  9   3
11  1   1   21  2
12  1   0   3   1
13  1   4   20  3
14  1   8   22  0
15  1   16  23  2
16  1   0   3   1
17  1   4   20  3
18  1   19  17  1
19  1   12  0   0

对于每个 ID,我想计算 c3 中的值(将它们视为类别),然后将值除以 ID 的长度。

例如: ID = 0 有 10 个观察值,c3.0 中有 3 个,c3.1 中有 3 个,c3.2 中有 3 个,c3.3 中有 1 个 ID = 1 有 10 个观察值,c3.0 中有 2 个,c3.1 中有 3 个,c3.2 中有 2 个,c3.3 中有 3 个

我想获得这样的东西:

ID c3.0  c3.1  c3.2   c3.3
0   0.3   0.3   0.3    0.1
1   0.2   0.3   0.2    0.3

列的名称不相关

感谢您的帮助!

我们可以使用groupby value_counts with normalize=True to count the occurences of 'c3' per 'id' normalized by total length of the group. Then unstack来得到宽形式:

out = df.groupby('id')['c3'].value_counts(normalize=True).unstack()

out:

c3    0    1    2    3
id                    
0   0.3  0.3  0.3  0.1
1   0.2  0.3  0.2  0.3

使用 add_prefix to update the column headers, and reset_index 进行一些清理以使 id 成为一列:

out = (
    df.groupby('id')['c3'].value_counts(normalize=True)
        .unstack()
        .rename_axis(columns=None)
        .add_prefix('c3.')
        .reset_index()
)

out:

   id  c3.0  c3.1  c3.2  c3.3
0   0   0.3   0.3   0.3   0.1
1   1   0.2   0.3   0.2   0.3

您可以使用 crosstab :

result = pd.crosstab(df.id, df.c3, normalize='index')

重命名列:

result.columns = [f'{result.columns.name}.{label}' for label in result.columns]


result.rename_axis(None)
 
   c3.0  c3.1  c3.2  c3.3
0   0.3   0.3   0.3   0.1
1   0.2   0.3   0.2   0.3