2017-04-20 6 views
2

Ich habe eine Pandas Datenrahmen, df, wie:Python Pandas: Aktualisieren Zeile basierend auf einer anderen Zeile Wert

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

Alle Werte in df sind Strings, die Zahlen darunter. Ich mag die grade numerischen Werte in Buchstaben umwandeln, bezogen auf die grade_type Spalt Überprüfung zu erhalten:

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

Für Vollständigkeit, die Zahl zu Buchstabegrad Umwandlungen sind:

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

Warum doesn Ist das Arbeit?

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... 

Die Alternative ist mit df.apply(...lambda:...), aber ich bin nicht so sicher, wie das ziehen aus, da wir die grade_type Spalt vor der Entscheidung, ob oder nicht zu aktualisieren, um den grade Wert zu überprüfen.

Antwort

2

Der Grund dafür, dass Ihr Dataframe nicht aktualisiert wird, ist, dass die von iterrows() zurückgegebenen Zeilen Kopien sind. Und du arbeitest an dieser Kopie.

können Sie verwenden die index von iterrows zurückgegeben und manipulieren Datenrahmen direkt:

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

Oder wie Sie gesagt haben können Sie df.apply() verwenden, und es eine benutzerdefinierte Funktion übergeben:

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) 

Sie können auch Verwenden Sie ifelse in Ihrem Lambda, um zu überprüfen, ob x['grade_type'] wie folgt numerisch ist, verwenden Sie den, der einfacher zu lesen aussieht.

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) 
Verwandte Themen