Python pandas применяет функцию, если значение столбца не равно NULL
у меня есть фрейм данных (в Python 2.7, pandas 0.15.0):
df=
A B C
0 NaN 11 NaN
1 two NaN ['foo', 'bar']
2 three 33 NaN
Я хочу применить простую функцию для строк, которые не содержат нулевых значений в определенном столбце. Моя функция максимально проста:
def my_func(row):
print row
и мой код применения следующий:
df[['A','B']].apply(lambda x: my_func(x) if(pd.notnull(x[0])) else x, axis = 1)
он отлично работает. Если я хочу проверить столбец " B " для нулевых значений pd.notnull()
отлично работает. Но если я выберу столбец "C", содержащий список объекты:
df[['A','C']].apply(lambda x: my_func(x) if(pd.notnull(x[1])) else x, axis = 1)
затем я получаю следующее сообщение об ошибке: 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')
кто-нибудь знает, почему pd.notnull()
работает только для целых и строковых столбцов, но не для "столбцов списка"?
и есть ли лучший способ проверить нулевые значения в столбце " C " вместо этого:
df[['A','C']].apply(lambda x: my_func(x) if(str(x[1]) != 'nan') else x, axis = 1)
спасибо!
3 ответов
проблема в том, что pd.notnull(['foo', 'bar'])
работает элементарно и возвращает array([ True, True], dtype=bool)
. Ваше условие if пытается преобразовать это в логическое значение, и именно тогда вы получите исключение.
чтобы исправить это, вы можете просто обернуть оператор isnull с np.all
:
df[['A','C']].apply(lambda x: my_func(x) if(np.all(pd.notnull(x[1]))) else x, axis = 1)
теперь вы увидите, что np.all(pd.notnull(['foo', 'bar']))
действительно True
.
также другой способ-просто использовать row.notnull().all()
(без numpy
), вот пример:
df.apply(lambda row: func1(row) if row.notnull().all() else func2(row), axis=1)
вот полный пример на вашем 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
и более дружелюбный скриншот: -)
у меня был столбец, содержащий списки и NaN
s. Так что следующая сработала на меня.
df.C.map(lambda x: my_func(x) if type(x) == list else x)