2014-10-28 9 views
12

Ho un dataframe (in Python 2.7, panda 0.15.0):Python panda funzione si applicano se un valore di colonna non è NULL

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

voglio applicare una semplice funzione per le righe che non contengono NULL valori in una colonna specifica. La mia funzione è il più semplice possibile:

def my_func(row): 
    print row 

E il mio codice applicare è la seguente:

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

Funziona perfettamente. Se voglio controllare la colonna "B" per i valori NULL, anche lo pd.notnull() funziona perfettamente. Ma se seleziono colonna 'C' che contiene gli oggetti della lista:

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

allora ottengo il seguente messaggio di errore: 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')

Qualcuno sa perché pd.notnull() funziona solo per interi e stringhe colonne, ma non per 'lista colonne?

E c'è un modo più bello per verificare la presenza di valori NULL nella colonna 'C' al posto di questo:

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

Grazie!

risposta

12

Il problema è che pd.notnull(['foo', 'bar']) opera elementwise e restituisce array([ True, True], dtype=bool). La tua condizione if cerca di convertirla in un booleano, e questo è il momento in cui ottieni l'eccezione.

Per risolvere il problema, si può semplicemente avvolgere la dichiarazione isnull con np.all:

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

Ora vedrai che np.all(pd.notnull(['foo', 'bar'])) è davvero True.

+0

nota che 'np.all ([True, True])' restituirà 'True'. Penso che funzionerà per l'OP. –

+0

@PaulH Grazie. Ho provato con 'all' ma ho trascurato' np.all'. Il problema non è con '[True, True]', ma piuttosto con 'False'. Mentre 'all (pd.notnull (None))' genera un errore, 'np.all (pd.notnull (None))' no. – Korem

+0

Grazie Korem, funziona! Quello che mi chiedo è che un singolo 'pd.notnull (df ['C'])' ritorni con 'False, True, False' ma non con' False, [True, True], False'. – ragesz

4

anche un altro modo è quello di utilizzare solo row.notnull().all() (senza numpy), ecco un esempio:

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

Ecco un esempio completo sul tuo 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 

e uno screenshot più amichevole: -)

enter image description here

0

Ho avuto una colonna conteneva elenchi e NaN s. Quindi, il prossimo ha funzionato per me.

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

Sono già state fornite migliori soluzioni. –