web-dev-qa-db-ja.com

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
_

特定の列にNULL値を含まない行に単純な関数を適用したい。私の機能は可能な限りシンプルです:

_def my_func(row):
    print row
_

私の適用コードは次のとおりです。

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

完璧に機能します。 NULL値の列 '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」のNULL値をチェックするより良い方法があります:

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

ありがとうございました!

21
ragesz

問題は、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であることがわかります。

20
Korem

また、別の方法は、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

そして、よりフレンドリーなスクリーンショット:-)

enter image description here

3
Aziz Alto

リストとNaNsを含む列がありました。だから、次のものは私のために働いた。

df.C.map(lambda x: my_func(x) if type(x) == list else x)
3
coffman21

試してみてください...

df['a'] = df['a'].apply(lambda x: x.replace(',','\,') if x != None else x)

この例では、値がNoneでない場合、カンマにエスケープ文字を追加します

0
Andrew Monger