web-dev-qa-db-ja.com

pandas DataFrameの前の値でNaNを置き換える方法は?

いくつかのNaNsを持つDataFrameがあるとします:

>>> import pandas as pd
>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df
    0   1   2
0   1   2   3
1   4 NaN NaN
2 NaN NaN   9

私がする必要があるのは、その上の同じ列のすべてのNaNを最初の非NaN値に置き換えることです。最初の行にNaNが含まれることはないと想定されています。したがって、前の例では、結果は次のようになります

   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

データフレーム全体を列ごと、要素ごとにループして値を直接設定できますが、これを達成する簡単な(最適なループフリーの)方法はありますか?

85
zegkljan

DataFrameで fillna メソッドを使用し、メソッドをffill(forward fill)として指定できます。

>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df.fillna(method='ffill')
   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

この方法...

最後の有効な観測値を次の有効な値に伝播します

逆の方法として、bfillメソッドもあります。

このメソッドは、DataFrameをインプレースで変更しません。返されたDataFrameを変数に再バインドするか、inplace=Trueを指定する必要があります。

df.fillna(method='ffill', inplace=True)
138
Alex Riley

受け入れられた答えは完璧です。関連するが、グループ内でのみ前方に記入する必要があるわずかに異なる状況がありました。誰かが同じニーズを持っている場合、fillnaがDataFrameGroupByオブジェクトで動作することを知ってください。

>>> example = pd.DataFrame({'number':[0,1,2,nan,4,nan,6,7,8,9],'name':list('aaabbbcccc')})
>>> example
  name  number
0    a     0.0
1    a     1.0
2    a     2.0
3    b     NaN
4    b     4.0
5    b     NaN
6    c     6.0
7    c     7.0
8    c     8.0
9    c     9.0
>>> example.groupby('name')['number'].fillna(method='ffill') # fill in row 5 but not row 3
0    0.0
1    1.0
2    2.0
3    NaN
4    4.0
5    4.0
6    6.0
7    7.0
8    8.0
9    9.0
Name: number, dtype: float64
15
ErnestScribbler

pandas.DataFrame.fillnamethod='ffill'オプションとともに使用できます。 'ffill'は 'forward fill'の略で、最後の有効な観測を前方に伝播します。代替手段は'bfill'で、同じように機能しますが、逆方向に機能します。

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
df = df.fillna(method='ffill')

print(df)
#   0  1  2
#0  1  2  3
#1  4  2  3
#2  4  2  9

物事を簡単にするために、このための直接同義語関数 pandas.DataFrame.ffill もあります。

12
Ffisegydd

この解決策を試してみたときに気づいたことの1つは、配列の最初または最後にN/Aがある場合、ffillとbfillはまったく機能しないことです。両方が必要です。

In [224]: df = pd.DataFrame([None, 1, 2, 3, None, 4, 5, 6, None])

In [225]: df.ffill()
Out[225]:
     0
0  NaN
1  1.0
...
7  6.0
8  6.0

In [226]: df.bfill()
Out[226]:
     0
0  1.0
1  1.0
...
7  6.0
8  NaN

In [227]: df.bfill().ffill()
Out[227]:
     0
0  1.0
1  1.0
...
7  6.0
8  6.0
8
jjs

ffillメソッドに同意するだけですが、もう1つの情報は、キーワード引数limitを使用してフォワードフィルを制限できることです。

>>> import pandas as pd    
>>> df = pd.DataFrame([[1, 2, 3], [None, None, 6], [None, None, 9]])

>>> df
     0    1    2
0  1.0  2.0  3.0
1  NaN  NaN  6.0
2  NaN  NaN  9.0

>>> df[1].fillna(method='ffill', inplace=True)
>>> df
     0    1    2
0  1.0  2.0  3.0
1  NaN  2.0  NaN
2  NaN  2.0  9.0

キーワード引数にlimitが追加されました

>>> df[0].fillna(method='ffill', limit=1, inplace=True)

>>> df
     0    1  2
0  1.0  2.0  3
1  1.0  2.0  6
2  NaN  2.0  9
3
user3724647

ffillには独自のメソッドがあります pd.DataFrame.ffill

df.ffill()

     0    1    2
0  1.0  2.0  3.0
1  4.0  2.0  3.0
2  4.0  2.0  9.0
2
piRSquared

1列のみのバージョン

  • NANを最後の有効な値で埋めます
df[column_name].fillna(method='ffill', inplace=True)
  • NANに次の有効な値を入力します
df[column_name].fillna(method='backfill', inplace=True)
1
DeveScie

私の場合、異なるデバイスからの時系列がありますが、いくつかのデバイスはある期間中に値を送信できませんでした。したがって、すべてのデバイスと期間についてNA値を作成し、その後でfillnaを実行する必要があります。

df = pd.DataFrame([["device1", 1, 'first val of device1'], ["device2", 2, 'first val of device2'], ["device3", 3, 'first val of device3']])
df.pivot(index=1, columns=0, values=2).fillna(method='ffill').unstack().reset_index(name='value')

結果:

        0   1   value
0   device1     1   first val of device1
1   device1     2   first val of device1
2   device1     3   first val of device1
3   device2     1   None
4   device2     2   first val of device2
5   device2     3   first val of device2
6   device3     1   None
7   device3     2   None
8   device3     3   first val of device3
0
Anton Shelin