使用 Python pandas 根据列值生成每个组的百分比

Posted

技术标签:

【中文标题】使用 Python pandas 根据列值生成每个组的百分比【英文标题】:Generate percentage for each group based on column values using Python pandas 【发布时间】:2019-08-30 09:50:59 【问题描述】:

我有一个如下所示的数据框。我想根据 subject_id、hadm_id 和 icusstay_id 对它们进行分组。一旦我对它进行分组,我想在“val_bw_80_110”列中提取超过 60% 个 1 的主题。从下面的例子中,我们可以看到 subject_id = 38 满足这个条件(val_bw_80_110 的所有值 = 1,这意味着 100%),我想提取属于 subject_id = 38 的组。如果只有两个 1那么百分比将是 66.666 等

我已经尝试过使用 groupby 但无法继续进行,因为我不确定如何获取列中值的百分比

data = [[38,10,110,1,0,0], [38,10,110,1,0,0],[38,10,110,1,0,0], 
[28,11,120,1,0,0],[28,11,120,0,1,0],[28,11,120,0,0,1],
   [48,13,130,1,0,0],[48,13,130,0,1,0],[48,13,130,0,0,1]] 
df = pd.DataFrame(data, columns =['subject_id','hadm_id','icustay_id',
'val_bw_80_110','val_lt_80','val_gt_110'])
new_df = df.groupby(['subject_id','hadm_id','icustay_id'])

我的预期结果只是一个数据框,其中包含满足 val_bw_80_110 中 1 的 60% 条件的所有主题。输出数据框应包含 subject_id = 38 的所有记录(以及列)

【问题讨论】:

预期输出是什么? 我认为最终的 DataFrame 看起来如何。 输出数据帧将包含所有 subject_id = 38 的记录,因为这是唯一一个超过 val_bw_80_110 中 1 的 60% 限制的 subject_id 【参考方案1】:

创建满足您条件的subject_id 的布尔索引,然后使用Series.isinDataFrame.loc 过滤它们。

s = df.groupby(['subject_id','hadm_id','icustay_id'])['val_bw_80_110'].mean().ge(0.6)

df.loc[df.subject_id.isin(s.index.levels[0][s])]

[输出]

   subject_id  hadm_id  icustay_id  val_bw_80_110  val_lt_80  val_gt_110
0          38       10         110              1          0           0
1          38       10         110              1          0           0
2          38       10         110              1          0           0

【讨论】:

【参考方案2】:

使用boolean indexingGroupBy.transform 获取1 值的百分比:

df1 = (df[df.groupby(['subject_id','hadm_id','icustay_id'])['val_bw_80_110']
            .transform('mean').ge(0.6)])
print (df1)
   subject_id  hadm_id  icustay_id  val_bw_80_110  val_lt_80  val_gt_110
0          38       10         110              1          0           0
1          38       10         110              1          0           0
2          38       10         110              1          0           0

如果使用transform 获取与原始DataFrame 大小相同的Series,则可以进行过滤:

print (df.groupby(['subject_id','hadm_id','icustay_id'])['val_bw_80_110']
            .transform('mean'))
0    1.000000
1    1.000000
2    1.000000
3    0.333333
4    0.333333
5    0.333333
6    0.333333
7    0.333333
8    0.333333
Name: val_bw_80_110, dtype: float64

print (df.groupby(['subject_id','hadm_id','icustay_id'])['val_bw_80_110']
            .transform('mean').ge(0.6))
0     True
1     True
2     True
3    False
4    False
5    False
6    False
7    False
8    False
Name: val_bw_80_110, dtype: bool

【讨论】:

只是想了解这两种解决方案。你能告诉我transform('mean')有什么用,而不是直接使用mean() 你能帮我写这篇相关的帖子吗? ***.com/questions/55592014/…

以上是关于使用 Python pandas 根据列值生成每个组的百分比的主要内容,如果未能解决你的问题,请参考以下文章

根据另一个数据框 python pandas 替换列值 - 更好的方法?

根据列值删除Python Pandas中的DataFrame行[重复]

根据其他列值/ Pandas -Python 在数据框中创建 ID 列

Python散点图设计 - 根据另一列值为x轴选择变量的特定值

如何根据Pandas中的其他列值计算每个年龄的平均值

Pandas Dataframe 根据列值将值展平到单元格