条件付き置換パンダ


123

DataFrameがあり、特定の列の値を超える値をゼロに置き換えたい。これはこれを達成する方法だと思っていました:

df[df.my_channel > 20000].my_channel = 0

チャネルを新しいデータフレームにコピーするのは簡単です。

df2 = df.my_channel 

df2[df2 > 20000] = 0

これは私が望んでいることとまったく同じですが、元のDataFrameの一部としてチャネルで機能していないようです。


ここであなたが探していたものを見つけまし
2017年

回答:


181

.ixインデクサーは0.20.0より前のpandasバージョンでは問題なく機能しますが、pandas 0.20.0以降、.ixインデクサーは非推奨になっているため、使用しないでください。代わりに、.locまたはilocインデクサーを使用できます。この問題は次の方法で解決できます。

mask = df.my_channel > 20000
column_name = 'my_channel'
df.loc[mask, column_name] = 0

または、1行で

df.loc[df.my_channel > 20000, 'my_channel'] = 0

maskが含まれている行を選択するのに役立ちますdf.my_channel > 20000True、名前がのdf.loc[mask, column_name] = 0列にmask保持されている選択された行に値0を設定しますcolumn_name

アップデート: このケースでは、使用する必要がありますlocあなたが使用している場合のでiloc、あなたが得るNotImplementedErrorことを占います整数型のiLocationベースブールインデックスは使用できませんが


81

試す

df.loc[df.my_channel > 20000, 'my_channel'] = 0

注: v0.20.0以降、/に置き換えix られて非推奨になりました。lociloc


8
ありがとうございました。私も自分の解決策を見つけました:df.my_channel [df.my_channel> 20000] = 0
BMichell

2
@BMichell私はあなたのソリューションが0.13で警告を出し始めるかもしれないと思う、まだ試す機会がなかった
lowtech

収量エラー:/opt/anaconda3/envs/python35/lib/python3.5/site-packages/ipykernel_launcher.py:1:SettingWithCopyWarning:Value is set to set to a copy of a slice from a DataFrameの警告を参照してくださいドキュメント:pandas.pydata.org/pandas-docs/stable/… "" "IPythonカーネルを起動するためのエントリポイント
Rutger Hofste

@RutgerHofste言及してくれてありがとう、さらに別の議論はPython3を決して使用しません
lowtech

34

np.where 関数は次のように機能します。

df['X'] = np.where(df['Y']>=50, 'yes', 'no')

あなたの場合あなたは望むでしょう:

import numpy as np
df['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)

19

元のデータフレームが更新されない理由は、連鎖インデックスによってデータフレームのビューではなくコピーが変更される可能性があるためです。ドキュメントはこの助言を与えます:

pandasオブジェクトに値を設定するときは、いわゆる連鎖インデックスを回避するように注意する必要があります。

あなたにはいくつかの選択肢があります:-

loc +ブールインデックス

loc 値の設定に使用でき、ブールマスクをサポートします。

df.loc[df['my_channel'] > 20000, 'my_channel'] = 0

mask +ブールインデックス

シリーズに割り当てることができます:

df['my_channel'] = df['my_channel'].mask(df['my_channel'] > 20000, 0)

または、シリーズを適切に更新できます。

df['my_channel'].mask(df['my_channel'] > 20000, 0, inplace=True)

np.where +ブールインデックス

あなたはできるあなたの状態のときに、あなたのオリジナルシリーズを割り当てることによって、numpyのを使用していない満足。ただし、最初の2つのソリューションは指定された値のみを明示的に変更するため、よりクリーンです。

df['my_channel'] = np.where(df['my_channel'] > 20000, 0, df['my_channel'])

0

私が使用するlambda上での機能をSeriesするDataFrame。このように:

f = lambda x: 0 if x>100 else 1
df['my_column'] = df['my_column'].map(f)

これが効率的な方法であるとは断言しませんが、問題なく機能します。


3
これは非効率的であり、行単位の演算にPythonレベルのループが含まれるため推奨されません。
2018年

ありがとう、locここではのように使用できると思います df.loc[: , 'my_column'] = df['my_column'].map(f)。以下に追加したような高速かどうかはわかりません。
Ozkan Serttas 2018年

2
いいえ、まだ列方向ではなく行方向で操作しているため、まだ遅いです。
jpp 2018年

0

これを試して:

df.my_channel = df.my_channel.where(df.my_channel <= 20000, other= 0)

または

df.my_channel = df.my_channel.mask(df.my_channel > 20000, other= 0)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.