Python pandas:根据另一列的值更新行

时间:2017-04-20 01:15:20

标签: python pandas

我有一个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}}值。

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)