2014-10-28 15 views
12

Mam dataframe (w Pythonie 2.7, pandy 0.15.0):Python pandy funkcję stosuje się, jeżeli wartość kolumna nie jest NULL

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

Chcę zastosować prostą funkcję do wierszy, które nie zawierają NULL wartości w określonej kolumnie. Moja funkcja jest tak proste, jak to możliwe:

def my_func(row): 
    print row 

A moja zastosować kod jest następujący:

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

To działa doskonale. Jeśli chcę sprawdzić kolumnę "B" dla wartości NULL, działa również doskonale pd.notnull(). Ale jeśli mam wybierać kolumny „C”, która zawiera lista obiektów:

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

następnie pojawia się następujący komunikat o błędzie: 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')

Czy ktoś wie dlaczego pd.notnull() działa tylko dla liczb całkowitych i ciągów kolumn, ale nie dla „listy kolumny "?

I tam jest ładniejszy sposób sprawdzić dla wartości NULL w kolumnie „C” zamiast tego:

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

Dziękujemy!

Odpowiedz

12

Problem polega na tym, że pd.notnull(['foo', 'bar']) działa elementycznie i zwraca array([ True, True], dtype=bool). Twój warunek jeśli spróbuje przekonwertować to na wartość logiczną i wtedy otrzymasz wyjątek.

Aby to naprawić, można po prostu zawinąć IsNull oświadczenie z np.all:

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

Teraz zobaczysz, że np.all(pd.notnull(['foo', 'bar'])) jest rzeczywiście True.

+0

Zauważ, że 'np.all ([True, True])' zwróci 'True'. Myślę, że to zadziała w OP. –

+0

@PaulH Dzięki. Próbowałem z 'all', ale zaniedbałem' np.all'. Problem nie dotyczy '[True, True]', ale raczej z 'False'. Podczas gdy 'all (pd.notnull (None)) podnosi błąd,' np.all (pd.notnull (None)) 'nie. – Korem

+0

Dziękuję Korem, to działa! Zastanawiam się, że pojedynczy 'pd.notnull (df ['C'])) powraca z' False, True, False', ale nie z 'False, [True, True], False'. – ragesz

4

również innym sposobem jest po prostu użyć row.notnull().all() (bez numpy), oto przykład:

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

Powyżej znajduje się pełna przykładów na 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 

oraz przyjaznej zrzucie ekranu: -)

enter image description here

0

Miałem kolumnę zawierającą listy i NaN s. Tak więc następny pracował dla mnie.

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

Lepsze rozwiązania już są. –