DataFrameの欠損値(NoneやNaN)を定数で埋める時、fillnaというメソッドをよく使っていましたが、
定数で埋める以外にもいろいろ指定ができることがわかったので紹介します。
ドキュメントはこちらです。
pandas.DataFrame.fillna — pandas 1.1.2 documentation
まず、サンプルとして欠損値を含むDataFrameを作っておきます。
import pandas as pd
import numpy as np
df = pd.DataFrame(
[[np.nan, 2, np.nan, 0],
[3, 4, np.nan, 1],
[np.nan, np.nan, np.nan, 5],
[np.nan, 3, np.nan, 4]],
columns=list('ABCD')
)
print(df)
"""
A B C D
0 NaN 2.0 NaN 0
1 3.0 4.0 NaN 1
2 NaN NaN NaN 5
3 NaN 3.0 NaN 4
"""
fillnaの一番基本的な使い方は定数を指定するものです。
例えば、0を渡せばNaNを0に置き換えたDataFrameを返します。(inplace=True も指定すれば、データフレームそのものを書き換えます)
print(df.fillna(0))
"""
A B C D
0 0.0 2.0 0.0 0
1 3.0 4.0 0.0 1
2 0.0 0.0 0.0 5
3 0.0 3.0 0.0 4
"""
いつもはこうやって、数値なら0、文字列なら空文字列(“”)で埋めるだけの使い方をしていました。
しかし、ドキュメントを読むと、定数で埋める以外にもいろいろできます。
まず、定数ではなく、 列名: 値 の辞書を渡すことで、列ごとに別々の値で埋めることができます。
fill_values = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
print(df.fillna(value=fill_values))
"""
A B C D
0 0.0 2.0 2.0 0
1 3.0 4.0 2.0 1
2 0.0 1.0 2.0 5
3 0.0 3.0 2.0 4
"""
そしてこれは、辞書の代わりに、indexに列名、valueに値を持つSeriesを渡しても同じ挙動になります。
fill_values_sr = pd.Series(fill_values)
print(fill_values_sr)
"""
A 0
B 1
C 2
D 3
dtype: int64
"""
print(df.fillna(value=fill_values_sr))
"""
A B C D
0 0.0 2.0 2.0 0
1 3.0 4.0 2.0 1
2 0.0 1.0 2.0 5
3 0.0 3.0 2.0 4
"""
これを応用すると、各列をその列の平均値や最大値、最小値で埋めることも簡単にできます。
平均値でやってみたコードが次です。
print(df.fillna(value=df.mean()))
"""
A B C D
0 3.0 2.0 NaN 0
1 3.0 4.0 NaN 1
2 3.0 3.0 NaN 5
3 3.0 3.0 NaN 4
"""
さて、ここまでは列単位である一定の値で欠損値を補完する方法でしたが、時系列データなどを扱っている時は、
一定の値ではなく、直前や直後の値で埋めたいこともあると思います。
実はこの fillna はそのようなケースにも対応しており、
method という引数に “backfill”か”bfill”を指定すれば直後の値、
“pad”, “ffill”を指定すれば直前の値で埋めることができます。
bfillとffillだけですがそれぞれ試してみたのが次のコードです。
print(df.fillna(method="bfill"))
"""
A B C D
0 3.0 2.0 NaN 0
1 3.0 4.0 NaN 1
2 NaN 3.0 NaN 5
3 NaN 3.0 NaN 4
"""
print(df.fillna(method="ffill"))
"""
A B C D
0 NaN 2.0 NaN 0
1 3.0 4.0 NaN 1
2 3.0 4.0 NaN 5
3 3.0 3.0 NaN 4
"""
以上のように、fillnaを使うと定数での補完(0埋めなど)以外にもいろんなことができることがわかりました。