2017-04-20 152 views
2

我有一个熊猫据帧,DF,如:Python的大熊猫:更新行基于另一个行值

name | grade | grade_type 
--------------------------- 
sarah | B  | letter 
alice | A  | letter 
eliza | C  | letter 
beth | 76 | numeral 
jones | 90 | numeral 

df所有值都是字符串,包括数字。我想了grade数值为字母转换的基础上,检查grade_type列,得到:

name | grade | grade_type 
--------------------------- 
sarah | B  | letter 
alice | A  | letter 
eliza | C  | letter 
beth | B  | numeral 
jones | A  | numeral 

为了完整,数字到字母等级转换为:

A: grade > 80 
B: 70 < grade <= 80 
C: 60 < grade <= 70 

为什么没有按这项工作?

for index, row in df.iterrows(): 
    if row.grade_type == "numeral": 
    grade_val = int(row.grade.values[0]) 
    if grade_val > 80: 
     row.grade = "A" # This assignment doesn't update row.grade! 
    elif... 

另一种方法是使用df.apply(...lambda:...),但我不太知道如何实现自己的目标,因为我们在决定是否更新grade值前检查grade_type列。

回答

2

DataFrame不更新的原因是因为从iterrows()返回的行是副本。你正在研究这个副本。

可以使用indexiterrows回来,直接操作数据框:

for index, row in df.iterrows(): 
    grade_val = int(row.grade.values[0]) 
    if grade_val > 80: 
     df.loc[index, 'grade'] = 'A' 
    ... 

或者就像你说的,你可以使用df.apply(),并通过它的自定义函数:

def get_grades(x): 
    if x['grade_type'] == 'letter': 
     return(x['grade_val']) 
    if x['grade_val'] > 80: 
     return "A" 
    ... 


df['grade'] = df.apply(lambda x: get_grades(x), axis=1) 

你也可以在你的lambda中使用ifelse来检查x['grade_type']是否是数字,如下所示,使用看起来更容易阅读的那个。

def get_grades(grade_val): 
    if grade_val > 80: 
     return "A" 
    ... 

df['grade'] = df.apply(lambda x: get_grades(x['grade']) 
         if x['grade_type'] == 'numeral' else x['grade'], axis=1) 
相关问题