首页 > 解决方案 > 按两列分组并使用列中的两个不同数据子集计算百分比

问题描述

我正在寻找解决方案,但一直卡住。

我有一个包含四列的数据框ID group type value。我想group, value根据列中的值对记录进行分组并计算百分比type。此列中只能存在两个值 ( numer, denom)。

我的数据如下所示:

df = pd.DataFrame({'ID': ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'D', 'D', 'E'],
                   'group': ['red', 'red', 'red', 'red', 'green', 'green', 'blue', 'blue', 'blue', 'blue', 'blue'],
                   'type': ['numer', 'denom', 'numer', 'denom', 'numer', 'denom', 'numer', 'denom', 'numer', 'denom',
                            'denom'],
                   'value': ['1', '1', '0', 'NaN', '2', '2', '1', '1', '2', '2', '2']
                   })
# df
   ID  group   type value
0   A    red  numer     1
1   A    red  denom     1
2   B    red  numer     0
3   B    red  denom   NaN
4   C  green  numer     2
5   C  green  denom     2
6   D   blue  numer     1
7   D   blue  denom     1
8   D   blue  numer     2
9   D   blue  denom     2
10  E   blue  denom     2

我想将计数除以每个分组对 ( )numer的计数,因此最终结果将如下所示:denomgroup, value

group  value  percent
red        0      0.0
           1      1.0
           2      0.0
         NaN      0.0
green      0      0.0
           1      0.0
           2      1.0
         NaN      0.0     
blue       0      0.0
           1      1.0
           2      0.5
         NaN      0.0

到目前为止,我一直在尝试对此应用类似的方法,就像在 SQL 中使用 Window 函数一样。我当前的代码没有计算我想要使用的值(数字计数/面额计数)。相反,它根据每个分组对中的小计计算百分比:

res = df.groupby(['group','value']).agg({'ID': 'count'})
pct_df = res.groupby(level=0).apply(lambda x: 100 * x / float(x.sum()))

#pct_df
               ID
group value      
blue  1      0.40
      2      0.60
green 2      1.00
red   0      0.25
      1      0.50
      NaN    0.25

标签: pythonpandasdataframe

解决方案


您可以apply在 groupby 之后使用,然后重新索引 multiindex 以生成所需的索引。

你也可以试试Series.values_count

def division(numer, denom):
    return numer / denom if denom else 0

res = df.groupby(['group','value'])['type'].apply(lambda col: division(sum(col.eq('numer')), sum(col.eq('denom')))).to_frame('percent')

index = pd.MultiIndex.from_product([df['group'].unique(), sorted(df['value'].unique())], names=res.index.names)

res = res.reindex(index, fill_value=0)
print(res)

             percent
group value         
red   0          0.0
      1          1.0
      2          0.0
      NaN        0.0
green 0          0.0
      1          0.0
      2          1.0
      NaN        0.0
blue  0          0.0
      1          1.0
      2          0.5
      NaN        0.0

推荐阅读