我有一个pandas数据帧,df,如:
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_type
列,然后再决定是否更新grade
1}}值。
答案 0 :(得分:3)
您的DataFrame未更新的原因是因为iterrows():返回的行是副本。而你正在制作那份副本。
您可以使用iterrows返回的index
并直接操作DataFrame:
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中使用if
else
来检查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)