在 pandas groupby 中使用 reindex 和 value_counts

Using reindex with value_counts in pandas groupby

提问人:zzzbbx 提问时间:11/17/2023 更新时间:11/17/2023 访问量:60

问:

我想将value_counts与 groupby 一起使用,并将所有标签保留在原始数据帧中。在下面的示例中,例如,

import pandas as pd
df = pd.DataFrame(
    {
        'month': [1, 1, 1, 1, 1, 1, 2, 2, 2],
        'day': [1, 1, 1, 2, 2, 2, 1, 1, 1],
        'value': [1, 2, 3, 4, 5, 6, 1, 1, 1],
    }
)
df.groupby(['month', 'day'])['value'].value_counts(normalize=True)

month  day  value
1      1    1        0.333333
            2        0.333333
            3        0.333333
       2    4        0.333333
            5        0.333333
            6        0.333333
2      1    1        1.000000

我想显示月和日的所有组合从 1 到 6 的所有值(未显示的值为零。

添加 ,会产生错误:.reindex(range(1, 6))

ValueError:缓冲区 dtype 不匹配,预期为“Python 对象”,但得到 “多头”

Python pandas group-by

评论


答:

0赞 mozway 11/17/2023 #1

将值列转换为(可选地使用 指定所有现有类别,然后将自动计算所有类别:categorycategories=[…]value_counts

df['value'] = pd.Categorical(df['value'])

df.groupby(['month', 'day'])['value'].value_counts(normalize=True)

输出:

month  day  value
1      1    2        0.333333
            1        0.333333
            3        0.333333
            4        0.000000
            5        0.000000
            6        0.000000
       2    4        0.333333
            6        0.333333
            5        0.333333
            1        0.000000
            2        0.000000
            3        0.000000
2      1    1        1.000000
            5        0.000000
            6        0.000000
            4        0.000000
            3        0.000000
            2        0.000000
       2    5        0.000000
            4        0.000000
            3        0.000000
            2        0.000000
            1        0.000000
            6        0.000000
Name: proportion, dtype: float64

评论

0赞 zzzbbx 11/17/2023
代码应该只在值列下添加缺失值,所以月份和日期应该与上面的输出一样
0赞 mozway 11/17/2023
@zzzbbx我明白了,为了清楚起见,最好使用确切的预期输出来编辑问题。也就是说,这是相同的逻辑,然后使用分类值(请参阅更新)
0赞 Shubham Bansal 11/17/2023 #2

您可以使用数据透视表来执行此操作,因为由于 group by 语句,您的数据帧具有多索引。如下所示 -

import pandas as pd
df = pd.DataFrame(
    {
        'month': [1, 1, 1, 1, 1, 1, 2, 2, 2],
        'day': [1, 1, 1, 2, 2, 2, 1, 1, 1],
        'value': [1, 2, 3, 4, 5, 6, 1, 1, 1],
    }
)

pivot = pd.pivot_table(df, index=['month', 'day'], columns=['value'], aggfunc=len, fill_value=0)
pivot = pivot.div(pivot.sum(axis=1), axis=0)
print(pivot)

输出:

value             1         2         3         4         5         6
month day                                                            
1     1    0.333333  0.333333  0.333333  0.000000  0.000000  0.000000
      2    0.000000  0.000000  0.000000  0.333333  0.333333  0.333333
2     1    1.000000  0.000000  0.000000  0.000000  0.000000  0.000000
1赞 PaulS 11/17/2023 #3

另一个可能的解决方案:

(df.groupby(['month', 'day'])['value']
 .apply(lambda x: x.value_counts(normalize=True)
        .reindex(range(1, 7), fill_value=0)
        .rename_axis('value'))
 .rename('proportion'))

输出:

month  day  value
1      1    1        0.333333
            2        0.333333
            3        0.333333
            4        0.000000
            5        0.000000
            6        0.000000
       2    1        0.000000
            2        0.000000
            3        0.000000
            4        0.333333
            5        0.333333
            6        0.333333
2      1    1        1.000000
            2        0.000000
            3        0.000000
            4        0.000000
            5        0.000000
            6        0.000000
Name: proportion, dtype: float64