AとBの2つの列を持つパンダのDataFrameがあるとします。このDataFrameを変更して(またはコピーを作成して)、Aが0のときは常にBが常にNaNになるようにします。これをどのように実現しますか?
私は以下を試しました
df['A'==0]['B'] = np.nan
と
df['A'==0]['B'].values.fill(np.nan)
成功せずに。
.loc
ラベルベースのインデックス作成に使用:
df.loc[df.A==0, 'B'] = np.nan
この式は、行にインデックスを付け、列を選択df.A==0
するブール系列を作成します。'B'
これを使用して、列のサブセットを変換することもできます。例:
df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2
パンダの内部については、なぜそれが機能するのかを正確に知るのに十分なことはわかりませんが、基本的な問題は、DataFrameにインデックスを付けると結果のコピーが返されることもあれば、元のオブジェクトのビューが返されることもあります。ここのドキュメントによると、この動作は根本的なnumpyの動作に依存します。([1] [2]ではなく)1回の操作ですべてにアクセスする方が、設定に役立つ可能性が高いことがわかりました。
これは、高度なインデックス作成に関するpandasのドキュメントからのものです。
このセクションでは、必要なものを正確に説明します。( .ixdf.loc
は非推奨になりました-多くの人が以下で指摘しているように)データフレームのクールなスライス/ダイシングに使用できることがわかりました。と。設定にも使用できます。
df.loc[selection criteria, columns I want] = value
したがって、ブレンの答えは、「すべての場所を見つけてdf.A == 0
、列を選択し、それを」B
に設定することです。np.nan
pandas 0.20 ix以降、非推奨になりました。正しい方法は、df.locを使用することです
これが実際の例です
>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
A B
0 0 NaN
1 1 0
2 0 NaN
>>>
ここのドキュメントで説明されているように、.loc
は主にラベルベースですが、ブール配列で使用することもできます。
したがって、上記で行っていることは、次の方法で適用するdf.loc[row_index, column_index]
ことです。
loc
パンダに変更する行のサブセットを通知しますrow_index
loc
を利用することもラベルベースであり、のラベルを使用して列を選択し'B'
ますcolumn_index
論理、条件、または一連のブール値を返す任意の演算を使用して、ブール値の配列を作成できます。上記の例では、rows
を含むものが必要です。これ0
を使用できるためdf.A == 0
、以下の例でわかるように、これは一連のブール値を返します。
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df
A B
0 0 2
1 1 0
2 0 5
>>> df.A == 0
0 True
1 False
2 True
Name: A, dtype: bool
>>>
次に、上記のブール値の配列を使用して、必要な行を選択および変更します。
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
A B
0 0 NaN
1 1 0
2 0 NaN
詳細については、ここで高度なインデックス作成ドキュメントを確認してください。
速度を大幅に上げるには、NumPyのwhere関数を使用します。
いくつかのゼロを含む100,000行の2列のDataFrameを作成します。
df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))
numpy.where
df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df.loc[df['a'] == 0, 'b'] = np.nan
3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numpy'swhere
は約4倍高速です
複数の列を置き換えるには、次を使用してnumpy配列に変換します.values
。
df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
代替案:
1つは私には最適に見えませんが、奇妙なことに、それをサポートするドキュメントが見つかりません
dataframe.column[フィルター条件]=変更する値
df.B[df.A==0] = np.nan
dataframe.loc [フィルター条件、変更する列]=変更する値
df.loc[df.A == 0, 'B'] = np.nan
dataframe.column = np.where(フィルター条件、trueの場合は値、falseの場合は値)
import numpy as np
df.B = np.where(df.A== 0, np.nan, df.B)
dataframe.column = df.apply(ラムダ行:条件がtrueの場合は値、falseの場合は値、列ではなく行を使用)
df.B = df.apply(lambda x: np.nan if x['A']==0 else x['B'],axis=1)
dataframe.column = [条件がtrueの場合は値、列aとbのzip関数からのリスト内の要素a、bの場合はfalseの場合は値]
df.B = [np.nan if a==0 else b for a,b in zip(df.A,df.B)]
PandasでDataFrameを変更するには、、など+=
の「シンタックスシュガー」演算子を使用できます。*=
/=
df.loc[df.A == 0, 'B'] = df.loc[df.A == 0, 'B'] / 2
あなたは書ける:
df.loc[df.A == 0, 'B'] /= 2
値を置き換えるには、PandasメソッドまたはNaN
を使用できます。例えば:mask
where
df = pd.DataFrame({'A': [1, 2, 3], 'B': [0, 0, 4]})
A B
0 1 0
1 2 0
2 3 4
df['A'].mask(df['B'] == 0, inplace=True) # other=np.nan by default
# df['A'].where(df['B'] != 0, inplace=True)
結果:
A B
0 NaN 0
1 NaN 0
2 3.0 4