繁体   English   中英

为什么我的内循环不能正常工作?

[英]Why isn't my inner loop working correctly?

我对 Pandas 数据帧比较陌生。 我有以下代码和 For 嵌套循环。

当循环碰到内循环时,就会出现问题。

import pandas as pd 

### Create Data Frames:
Patients = {'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']}

pdf = pd.DataFrame(Patients)
print(pdf) ## DF printed out completely 

## 
i = 0

for Smokes in pdf.Smokes:
    if Smokes == 'Yes':
        pdf.at[i, 'Risk'] = 'high'
    else: 
       pdf.at[i, 'Risk'] = ' '
       for BMI in pdf.BMI:
           if BMI >= 30 or BMI <= 19:
               pdf.at[i, 'Risk'] = 'high'
           elif BMI >= 25 and BMI <=29:
               pdf.at[i, 'Risk'] = 'medium'
           else: 
               pdf.at[i, 'Risk'] = 'Low'
    i +=1 #

但是,当我再次打印出 pdf 时,它显示:

   Name  Age Sex  BMI Smokes  Risk
0  Jordan   26   M   26     No   Low
1    Jess   23   F   22     No   Low
2    Jake   19   M   24    Yes  high
3   Alice   20   F   17     No   Low
4    Alan   24   M   35    Yes  high
5  Lauren   28   F   20     No   Low

Jordan 应该是中等风险患者,Alice 应该是低风险患者,但内部循环没有意识到这一点。 但是,当我单独运行 BMI 循环时,它会识别它。

不要循环。 使用np.select创建条件层次结构和相应的选择并分配正确的值。 它优先于条件中找到的第一个True ,因此我们将其排序为'high''medium''low'

import numpy as np

conditions = [df['Smokes'].eq('Yes') | df['BMI'].ge(30) | df['BMI'].le(19),  # high
              df['BMI'].between(25, 30)]                                     # medium
choice_list = ['high', 'medium']

df['Risk'] = np.select(conditions, choice_list, default='low')

     Name  Age Sex  BMI Smokes    Risk
0  Jordan   26   M   26     No  medium
1    Jess   23   F   22     No     low
2    Jake   19   M   24    Yes    high
3   Alice   20   F   17     No    high
4    Alan   24   M   35    Yes    high
5  Lauren   28   F   20     No     low

在第一个else语句中,您有一个for循环,它再次评估所有Risk值,您应该在没有内部for循环的情况下使用您的代码:

if Smokes == 'Yes':
    pdf.at[i, 'Risk'] = 'high'
elif pdf.at[i, 'BMI'] >= 30 or pdf.at[i, 'BMI'] <= 19:
       pdf.at[i, 'Risk'] = 'high'
elif pdf.at[i, 'BMI'] >= 25 and pdf.at[i, 'BMI'] <=29:
       pdf.at[i, 'Risk'] = 'medium'
else: 
    pdf.at[i, 'Risk'] = 'Low'

在您的代码中进行这些小改动 pdf 将是:

在此处输入图像描述

可能值得将您的代码重构为类似

def get_risk(row):
    if row['Smokes'] == 'Yes':
        return 'high'
    elif row['BMI'] >= 30 or row['BMI'] <= 19:
        return 'high'
    elif row['BMI'] >= 25 and row['BMI'] <=29:
        return 'medium'
    else:
        return 'low'

pdf['Risk'] = pdf.apply(get_risk, axis=1)

我不确定您的风险计算中的逻辑是否能满足您的期望。 我从您的示例中逐字复制它。

通常在使用 pandas 数据帧时,有一些有效的方法可以在不使用for循环的情况下完成任务。 在您的情况下,您可以定义返回“风险”值字符串的 function 并将其apply每行的列以设置所需的新列:

import pandas as pd 

# create dataframe
Patients = {'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']}
pdf = pd.DataFrame(Patients)
# inspect dataframe
print(pdf)

# define the function that you want to apply
def get_risk(series):

    if series.Smokes == 'Yes':
        return 'high'    
    else:
        if series.BMI >= 30 or series.BMI <= 19:
            return 'high'
        elif series.BMI >= 25 and series.BMI <= 29:
            return 'medium'
        else:
            return 'low'

# apply the function across the columns of the dataframe (sending each row to the function as a series)
pdf['Risk'] = pdf.apply(get_risk, axis='columns')

# inspect the results
print(pdf)

您的内部 for 循环完成并设置pdf.at[i, 'Risk'] = 'Low'因为最后一个 BMI(20)很好。 这发生在外循环的每个循环上。

import pandas as pd 

### Create Data Frames:
Patients = {'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']}

pdf = pd.DataFrame(Patients)

risk = []
for index,rows in pdf.iterrows():
    if rows['Smokes'] == 'Yes':
          risk.append('high')
    else: 
       BMI = rows['BMI']
       if BMI >= 30 or BMI <= 19:
             risk.append('high')
       elif BMI >= 25 and BMI <=29:
             risk.append('medium')
       else: 
             risk.append('Low') 
pdf['risk']=risk

说明: iterrows() 有助于遍历 dataframe 的每一行。 'rows' 将包含所有值。 PS Alice 将处于高风险状态,因为 BMI 低于 19。我考虑了一个单独的列表“风险”,我在其中为每一行附加值并最后在 dataframe 中添加此列

使用它代替 for 循环,它非常干净和快速:

import numpy as np
pdf['Risk'] = np.where(pdf['Smokes']=='Yes', 'High','none')

pdf['Risk'] = np.where(np.logical_and(pdf['Smokes']=='No', pdf['Age']==26), 'medium','none')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM