2017-04-20 151 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) 
相關問題