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!
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
.
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 :-)
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)