178

AとBの2つの列を持つパンダのDataFrameがあるとします。このDataFrameを変更して(またはコピーを作成して)、Aが0のときは常にBが常にNaNになるようにします。これをどのように実現しますか?

私は以下を試しました

df['A'==0]['B'] = np.nan

df['A'==0]['B'].values.fill(np.nan)

成功せずに。

4

7 に答える 7

284

.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回の操作ですべてにアクセスする方が、設定に役立つ可能性が高いことがわかりました。

于 2012-09-06T19:37:18.910 に答える
102

これは、高度なインデックス作成に関するpandasのドキュメントからのものです

このセクションでは、必要なものを正確に説明します。( .ixdf.locは非推奨になりました-多くの人が以下で指摘しているように)データフレームのクールなスライス/ダイシングに使用できることがわかりました。と。設定にも使用できます。

df.loc[selection criteria, columns I want] = value

したがって、ブレンの答えは、「すべての場所を見つけてdf.A == 0、列を選択し、それを」Bに設定することです。np.nan

于 2012-09-26T17:14:39.427 に答える
30

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

詳細については、ここで高度なインデックス作成ドキュメントを確認してください

于 2017-07-04T20:27:54.927 に答える
17

速度を大幅に上げるには、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倍高速です

于 2017-11-02T23:18:25.170 に答える
5

複数の列を置き換えるには、次を使用してnumpy配列に変換します.values

df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
于 2017-10-25T04:22:16.613 に答える
0

代替案:

1つは私には最適に見えませんが、奇妙なことに、それをサポートするドキュメントが見つかりません

  1. 列をシリーズとしてフィルター処理します(注:フィルターは、列が書き込まれる前ではなく、書き込まれた後に表示されます)

dataframe.column[フィルター条件]=変更する値

df.B[df.A==0] = np.nan
  1. loc

dataframe.loc [フィルター条件、変更する列]=変更する値

df.loc[df.A == 0, 'B'] = np.nan
  1. numpy where

dataframe.column = np.where(フィルター条件、trueの場合は値、falseの場合は値)

import numpy as np
df.B = np.where(df.A== 0, np.nan, df.B)
  1. ラムダを適用する

dataframe.column = df.apply(ラムダ行:条件がtrueの場合は値、falseの場合は値、列ではなく行を使用)

df.B = df.apply(lambda x: np.nan if x['A']==0 else x['B'],axis=1)
  1. zipおよびlist構文

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)]
于 2021-12-09T13:50:44.803 に答える
0

PandasでDataFrameを変更するには、、など+=の「シンタックスシュガー」演算子を使用できます。*=/=

df.loc[df.A == 0, 'B'] = df.loc[df.A == 0, 'B'] / 2

あなたは書ける:

df.loc[df.A == 0, 'B'] /= 2

値を置き換えるには、PandasメソッドまたはNaNを使用できます。例えば:maskwhere

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
于 2021-12-14T07:43:41.283 に答える