使用条件从数据框创建列表

4

我需要创建一个患者列表,根据他们的BMI和是否吸烟将其分类为“高”,“中”或“低”。但是,当我当前运行代码时,六个条目都会显示“中”(使用了伪名称和数据)。

df = pd.DataFrame({'Name':['Jordan', 'Jess', 'Jake', 'Alice', 'Alan', 'Lauren'],
                   'Age':[26, 23, 19, 20, 24, 28],
                   'Sex':['M', 'F' , 'M', 'F', 'M', 'F'],
                   'BMI':[26, 22, 24, 17, 35, 20],
                   'Smokes':['No', 'No', 'Yes', 'No', 'Yes', 'No']})


risk_list = []

for i in df.Name:
  if df.BMI.any() > 30 | df.BMI.any() < 19.99 | df.Smokes.any() == "Yes":
    risk_list.append("High")
  elif df.BMI.any() >= 25 & df.BMI.any() <= 29.99:
    risk_list.append("Medium")
  elif df.BMI.any() < 24.99 & df.BMI.any() > 19.99 and df.Smokes.any() == "No":
    risk_list.append("Low")

print(risk_list)

输出:

['Medium', 'Medium', 'Medium', 'Medium', 'Medium', 'Medium']

我刚接触pandas和Python。我认为我很接近解决问题,但是不能弄清楚为什么我的数据没有正确返回。

谢谢。

3个回答

4
您的代码中有很多要素,以下是其中的一些:
  1. 您需要使用几个括号:df.BMI.any() > 30 | df.BMI.any() < 19.99 应为 (df.BMI.any() > 30) | (df.BMI.any() < 19.99)

  2. &and 是不同的。

  3. 循环内的所有内容(例如df.BMI.any())都独立于您正在查看的行(即Name),因此您将在任何地方获得相同的值。

我认为您可以使用np.select

np.select([df.BMI.gt(30) | df.BMI.lt(19.99) | df.Smokes.eq('Yes'),
           df.BMI.between(25,29.99)],
          ['High', 'Medium'], 'Low')

输出:

array(['Medium', 'Low', 'High', 'High', 'High', 'Low'], dtype='<U6')

2
除了@QuangHoang的回答之外,遍历数据框有点直观。你使用.iterrows(),而不是你的Name列,因为这不是一个字典。
risk_list = []

for _, i in df.iterrows():
    if i.BMI > 30 or i.BMI < 19.99 or i.Smokes == "Yes":
        risk_list.append("High")
    elif i.BMI >= 25 and i.BMI <= 29.99:
        risk_list.append("Medium")
    elif i.BMI < 24.99 and i.BMI > 19.99 and i.Smokes == "No":
        risk_list.append("Low")

>>> print(risk_list)
    ['Medium', 'Low', 'High', 'High', 'High', 'Low']

4
iterrows 可以作为一种便利的解决方案,但是它存在性能问题。使用 .apply 会更好。 - Derek O
2
是的,仅出于这个原因,我随时都会选择 np.select,但由于他对Python和pandas还很陌生,并且对如何访问数据框中的值感到困惑,所以这是一个很好的起点。 - Camilo Martinez M.

2
您可以将其定义为一个函数并将其传递给.apply()
def risk_eval(row):
  if row.BMI > 30 | row.BMI < 19.99 | row.Smokes== "Yes":
    return "High"
  elif row.BMI >= 25 & row.BMI <= 29.99:
    return"Medium"
  elif rowBMI < 24.99 & row.BMI> 19.99 and row.Smokes == "No":
    return "Low"

df['Risk'] = df.apply(lambda x: risk_eval(x),axis=1)

然后使用以下命令获取列表:

df['Risk'].values.tolist()

2
在我看来,这个答案最直观,我认为对于相对新手的pandas用户来说,这是学习使用apply的好方法。 - Derek O
1
同意并感谢,我最初想到的是 np.where(),但由于有太多条件,我认为这种方法会更简单明了。 - Celius Stingher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接