2014-10-28 7 views
12

ich einen Datenrahmen haben (in Python 2.7, Pandas 0.15.0):Python Pandas gelten Funktion, wenn ein Spaltenwert nicht NULL ist

df= 
     A B    C 
0 NaN 11    NaN 
1 two NaN ['foo', 'bar'] 
2 three 33    NaN 

ich eine einfache Funktion für die Zeilen anwenden möchten, die nicht NULL enthält Werte in einer bestimmten Spalte. Meine Funktion ist so einfach wie möglich:

def my_func(row): 
    print row 

Und mein anwenden-Code ist der folgende:

df[['A','B']].apply(lambda x: my_func(x) if(pd.notnull(x[0])) else x, axis = 1) 

Es funktioniert perfekt. Wenn ich die Spalte 'B' für NULL-Werte überprüfen möchte, funktioniert die pd.notnull() auch perfekt. Aber wenn ich Spalte ‚C‘ auswählen, die enthält eine Liste Objekte:

df[['A','C']].apply(lambda x: my_func(x) if(pd.notnull(x[1])) else x, axis = 1) 

dann bekomme ich folgende Fehlermeldung: ValueError: ('The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()', u'occurred at index 1')

Weiß jemand, warum pd.notnull() funktioniert nur für Integer- und String-Spalten, aber nicht für ‚-Liste Säulen'?

Und gibt es eine schönere Art und Weise für NULL-Werte in Spalte ‚C‘ statt dies zu überprüfen:

df[['A','C']].apply(lambda x: my_func(x) if(str(x[1]) != 'nan') else x, axis = 1) 

Vielen Dank!

Antwort

12

Das Problem ist, dass pd.notnull(['foo', 'bar']) elementweise funktioniert und array([ True, True], dtype=bool) zurückgibt. Ihre if-Bedingung versucht, das in einen booleschen Wert umzuwandeln, und dann erhalten Sie die Ausnahme.

es zu beheben, können Sie einfach die isnull Anweisung mit np.all wickeln:

df[['A','C']].apply(lambda x: my_func(x) if(np.all(pd.notnull(x[1]))) else x, axis = 1) 

Sie werden nun sehen, dass in der Tat np.all(pd.notnull(['foo', 'bar']))True ist.

+0

Beachten Sie, dass 'np.all ([True, True])' 'True' zurückgibt. Ich denke, das wird für das OP funktionieren. –

+0

@PaulH Danke. Ich habe es mit 'all' versucht, aber' np.all' vernachlässigt. Das Problem liegt nicht bei '[True, True]', sondern eher bei 'False'. Während 'all (pd.notnull (None))' einen Fehler verursacht, 'np.all (pd.notnull (None))' nicht. – Korem

+0

Danke, Korem, es funktioniert! Was ich mich wundere ist, dass eine einzelne 'pd.notnull (df ['C'])' mit 'False, True, False' zurückkehrt, aber nicht mit' False, [True, True], False'. – ragesz

4

Auch ist eine andere Art und Weise nur row.notnull().all() zu verwenden (ohne numpy), hier ein Beispiel:

df.apply(lambda row: func1(row) if row.notnull().all() else func2(row), axis=1) 

Hier ist ein vollständiges Beispiel auf Ihrem df:

>>> d = {'A': [None, 2, 3, 4], 'B': [11, None, 33, 4], 'C': [None, ['a','b'], None, 4]} 
>>> df = pd.DataFrame(d) 
>>> df 
    A  B  C 
0 NaN 11.0 None 
1 2.0 NaN [a, b] 
2 3.0 33.0 None 
3 4.0 4.0  4 
>>> def func1(r): 
...  return 'No' 
... 
>>> def func2(r): 
...  return 'Yes' 
... 
>>> df.apply(lambda row: func1(row) if row.notnull().all() else func2(row), axis=1) 
0 Yes 
1 Yes 
2 Yes 
3  No 

Und ein freundlicher Screenshot: -)

enter image description here

0

Ich hatte eine Spalte mit Listen und NaN s. Also, der nächste hat für mich funktioniert.

df.C.map(lambda x: my_func(x) if type(x) == list else x) 
+0

Bessere Lösungen sind bereits gegeben. –

Verwandte Themen