pandas column set value 使用多个列和多个条件

pandas column set value using multiple columns and multiple conditions

考虑这个示例数据:

data = {'January': [1,2,2,1,1], 'February': [1,1,2,0,0], 'March': [1,1,2,1,1], 'April': [1,1,2,0,0], 'May': [1,1,2,1,2], 'Frailty':['Moderate', 'Severe', 'Severe', 'Mild', 'Severe']}
sam_data = pd.DataFrame(data)

January February    March   April   May Frailty
1         1         1         1      1  Moderate
2         1         1         1      1  Severe
2         2         2         2      2  Severe
1         0         1         0      1  Mild
1         0         1         0      2  Severe

我正在尝试创建最后一列 'Met_Gap',它使用以下逻辑:

如果 Frailty = 'Severe' 并且每一列(1 月至 5 月)的值至少为 2,则 'Met',否则 'Gap' AND 如果 Frailty 1= 'Severe' 并且每列(1 月至 5 月)的值至少为 1,则 'Met' 否则 'Gap'

我不能只添加这些列并得到总计,因为要实现 'Met' 每个月的列中必须有某种非 0 的值。

在下面尝试过,没有成功。

df['Met_Gap'] = np.where((df[df.columns[:5]] >= 10) & (df['Frailty'] == 'Severe'), 'Met', 'Gap')

有点卡住了,因为我已经评估了每一列是否不为 0,如果一列是 0,它会自动成为 'Gap.' 但是,如果所有列都非零,那么对于 'Severe' 它们必须至少为 2,对于其他类别,至少为 1。

预期输出:

 January  February  March   April   May Frailty   Met_Gap
     1       1        1      1       1  Moderate    Met
     2       1        1      1       1  Severe      Gap
     2       2        2      2       2  Severe      Met
     1       0        1      0       1  Mild        Gap
     1       0        1      0       2  Severe      Gap

我相信有创意的人以前遇到过这个问题。感谢您的观看。

IIUC,您可以使用布尔掩码和 numpy.where/numpy.select:

cols = list(sam_data.columns[:5])
# ['January', 'February', 'March', 'April', 'May']

s = sam_data[cols].min(axis=1) # min value per row
m = sam_data['Frailty'].eq('Severe')

sam_data['result'] = np.where((m&s.ge(2))|((~m)&s.ge(1)), 'Met', 'Gap')

# alternative to set different values Met1/Met2 for example
#sam_data['result'] = np.select([m&s.ge(2), (~m)&s.ge(1)], ['Met', 'Met'], 'Gap')

输出:

   January  February  March  April  May   Frailty result
0        1         1      1      1    1  Moderate    Met
1        2         1      1      1    1    Severe    Gap
2        2         2      2      2    2    Severe    Met
3        1         0      1      0    1      Mild    Gap
4        1         0      1      0    2    Severe    Gap