Python pandas appliquer la fonction si une valeur de colonne N'est pas nulle

j'ai une dataframe (en Python 2.7, pandas 0.15.0):

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

je veux appliquer une fonction simple pour les lignes qui ne contiennent pas de valeurs nulles dans une colonne spécifique. Ma fonction est aussi simple que possible:

def my_func(row):
    print row

Et appliquer mon code est le suivant:

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

cela fonctionne parfaitement. Si je veux cocher la colonne' B ' pour les valeurs nulles, le pd.notnull() fonctionne parfaitement. Mais si je sélectionne la colonne " C " qui contient la liste objets:

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

puis-je obtenir le message d'erreur suivant: 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')

quelqu'un sait pourquoi pd.notnull() ne fonctionne que pour les colonnes entières et les chaînes de caractères, mais pas pour les 'colonnes de liste'?

Et est-il une plus belle façon de vérifier les valeurs NULL dans la colonne " C " au lieu de:

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

Merci!

17
demandé sur ragesz 2014-10-28 20:15:31

3 réponses

Le problème est que pd.notnull(['foo', 'bar']) utilise elementwise et retourne array([ True, True], dtype=bool). Votre condition if essaye de convertir cela en booléen, et c'est là que vous obtenez l'exception.

pour le corriger, vous pouvez simplement envelopper la déclaration isnull avec np.all:

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

Maintenant, vous allez voir que np.all(pd.notnull(['foo', 'bar'])) en effet True.

13
répondu Korem 2014-10-28 17:59:47

Aussi une autre façon est de simplement utiliser row.notnull().all() (sans les numpy), voici un exemple:

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

Voici un exemple complet sur votre 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

Et un plus convivial capture d'écran :-)

enter image description here

3
répondu Aziz Alto 2017-07-19 03:24:07

j'avais une colonne contenant des listes et NaN S. Le suivant a marché pour moi.

df.C.map(lambda x: my_func(x) if type(x) == list else x)
1
répondu coffman21 2017-11-22 10:24:16