pandasのinterpolate()の使い方|欠損値の線形補間・時系列のtime・limitの指定とffillとの違い

pandasの interpolate() は、欠損値(NaN)を前後の値から計算して埋めるメソッドです。引数なしの df.interpolate() は前後の値を直線で結ぶ線形補間で、先頭のNaNは埋まらず、末尾のNaNは直前の値で埋まります。日時のインデックスで間隔を考慮するなら method="time"、埋める範囲は limit・limit_direction・limit_area で調整します。

この記事では、interpolate() の既定の動き、fillna()・ffill() との違い、主な引数とmethodの選び方、グループごとの補間、pandas 3.0で使えなくなった書き方を、実行結果つきで説明します。コードは pandas 3.0.6(PyPIで2026年9月17日公開)、SciPy 1.18.1、Python 3.12.15 で実行しました。引数の仕様は公式リファレンス(DataFrame.interpolate)によります(いずれも2026年10月14日確認)。

interpolate() の基本と fillna()・ffill() との違い

import numpy as np
import pandas as pd

s = pd.Series([10, np.nan, np.nan, 40, np.nan, 60])
print(pd.DataFrame({"元": s, "interpolate": s.interpolate(), "ffill": s.ffill(), "fillna(0)": s.fillna(0)}))
      元  interpolate  ffill  fillna(0)
0  10.0         10.0   10.0       10.0
1   NaN         20.0   10.0        0.0
2   NaN         30.0   10.0        0.0
3  40.0         40.0   40.0       40.0
4   NaN         50.0   40.0        0.0
5  60.0         60.0   60.0       60.0

10と40の間の2つのNaNは、10→40を3等分して20と30になりました。ffill() は直前の値をそのまま写し、fillna(0) は決まった値で埋めます。気温やセンサーの値のように「途中もなめらかに変化していたはず」のデータには interpolate()、在庫数や設定値のように「次に変わるまで同じ値が続く」データには ffill() が向いています。fillna() の使い方は欠損値NaNを賢く埋める!fillnaでデータクレンジングで解説しています。

先頭・末尾のNaNはどうなるか:limit_direction と limit_area

import numpy as np
import pandas as pd

s = pd.Series([np.nan, 1, np.nan, 3, np.nan, np.nan])
print(pd.DataFrame({
    "元": s,
    "既定": s.interpolate(),
    "both": s.interpolate(limit_direction="both"),
    "inside": s.interpolate(limit_area="inside"),
}))
     元   既定  both  inside
0  NaN  NaN   1.0     NaN
1  1.0  1.0   1.0     1.0
2  NaN  2.0   2.0     2.0
3  3.0  3.0   3.0     3.0
4  NaN  3.0   3.0     NaN
5  NaN  3.0   3.0     NaN
指定 先頭のNaN 途中のNaN 末尾のNaN
既定(limit_direction=”forward”) NaNのまま 補間 直前の値で埋まる
limit_direction=”both” 直後の値で埋まる 補間 直前の値で埋まる
limit_area=”inside” NaNのまま 補間 NaNのまま
limit_area=”outside” NaNのまま(”both”と併用すると埋まる) 埋めない 直前の値で埋まる

線形補間は両側に値があって初めて計算できるので、先頭のNaNは前に値がなく埋まりません。一方、末尾のNaNは既定では直前の値で埋まります。末尾まで勝手に埋めたくない(実測値がない区間を作りたくない)ときは、limit_area="inside" を指定すると「前後を有効な値に挟まれたNaN」だけが埋まります。

連続するNaNの埋める数を制限する:limit

import numpy as np
import pandas as pd

s = pd.Series([1, np.nan, np.nan, np.nan, 5])
print(pd.DataFrame({
    "元": s,
    "limit=1": s.interpolate(limit=1),
    "limit=1,both": s.interpolate(limit=1, limit_direction="both"),
}))
     元  limit=1  limit=1,both
0  1.0      1.0           1.0
1  NaN      2.0           2.0
2  NaN      NaN           NaN
3  NaN      NaN           4.0
4  5.0      5.0           5.0

limit は「連続するNaNを最大いくつまで埋めるか」です。既定の向きでは前から1つだけ埋まり、limit_direction="both" にすると前後から1つずつ埋まります。長い欠測区間を補間で埋めすぎないための安全装置として使えます。埋まった値は、両端の1と5を結ぶ直線上の値(2と4)です。

日時のインデックスでは method=”time” を使う

import numpy as np
import pandas as pd

idx = pd.to_datetime(["2026-10-01", "2026-10-02", "2026-10-05", "2026-10-06"])
s = pd.Series([10.0, np.nan, np.nan, 40.0], index=idx)
print(pd.DataFrame({"元": s, "linear": s.interpolate(), "time": s.interpolate(method="time")}))
               元  linear  time
2026-10-01  10.0    10.0  10.0
2026-10-02   NaN    20.0  16.0
2026-10-05   NaN    30.0  34.0
2026-10-06  40.0    40.0  40.0

既定の method="linear" はインデックスを無視して、行が等間隔に並んでいるものとして計算します。上の例は10月2日の次が10月5日と3日空いていますが、linear では20・30と均等に埋まりました。method="time" は日時の間隔に比例して計算するので、1日目の16、4日目の34という値になります。日付が飛び飛びの時系列では time を使ってください。インデックスが日時ではなく数値のときは、同じ考え方の method="index" を使います。

曲線で補間する:polynomial・spline・pchip

import numpy as np
import pandas as pd

s = pd.Series([0.0, 1.0, np.nan, 9.0, 16.0, np.nan, 36.0])   # 0,1,4,9,16,25,36 の一部が欠けている
print(pd.DataFrame({
    "元": s,
    "linear": s.interpolate(),
    "polynomial(2)": s.interpolate(method="polynomial", order=2),
    "spline(3)": s.interpolate(method="spline", order=3),
    "pchip": s.interpolate(method="pchip"),
}).round(3))
      元  linear  polynomial(2)  spline(3)   pchip
0   0.0     0.0            0.0        0.0   0.000
1   1.0     1.0            1.0        1.0   1.000
2   NaN     5.0            4.0        4.0   4.062
3   9.0     9.0            9.0        9.0   9.000
4  16.0    16.0           16.0       16.0  16.000
5   NaN    26.0           25.0       25.0  25.019
6  36.0    36.0           36.0       36.0  36.000

0, 1, 4, 9, 16, 25, 36(xの2乗)の一部を欠かせたデータです。直線で結ぶ linear は5と26になりますが、2次の多項式 polynomial(order=2)と3次のスプライン spline(order=3)は4と25を復元しました。pchip は値の増減の向きを保つ補間で、行き過ぎ(オーバーシュート)が起きにくい方法です。これらは内部でSciPyの補間関数を使うため、SciPyのインストールが必要です。また polynomial と spline は order の指定が必須です。

曲線の補間は「データが本当にその形をしている」ときだけ有効です。よく分からないときは linear(日時なら time)を使い、補間した値をグラフで確かめましょう。

method 計算のしかた 向いているデータ
linear(既定) 行を等間隔とみなして直線で結ぶ 等間隔に並んだデータ全般
time 日時の間隔に比例して直線で結ぶ 日付が飛び飛びの時系列
index / values インデックスの数値に比例して直線で結ぶ 数値のインデックスが不等間隔なデータ
nearest いちばん近い有効な値を使う カテゴリに近い数値、段階的に変わる値
polynomial / spline 多項式・スプラインの曲線で結ぶ(order必須) なめらかな曲線になることが分かっている値
pchip / akima 形を保つ区分的な3次曲線 行き過ぎを避けたい曲線的な値

グループごとに補間する

import numpy as np
import pandas as pd

df = pd.DataFrame({
    "店舗": ["A", "A", "A", "B", "B", "B"],
    "売上": [100, np.nan, 300, np.nan, 60, 80],
})
df["全体で補間"] = df["売上"].interpolate()
df["店舗ごとに補間"] = df.groupby("店舗")["売上"].transform(lambda x: x.interpolate())
print(df)
  店舗     売上  全体で補間  店舗ごとに補間
0  A  100.0  100.0    100.0
1  A    NaN  200.0    200.0
2  A  300.0  300.0    300.0
3  B    NaN  180.0      NaN
4  B   60.0   60.0     60.0
5  B   80.0   80.0     80.0

縦に複数の店舗や銘柄が並んだデータを列全体で補間すると、別のグループの値をまたいで計算してしまいます。上の例では店舗Bの先頭のNaNが、店舗Aの300と店舗Bの60から180と計算されました。groupby().transform(lambda x: x.interpolate()) でグループ内だけで補間すれば、Bの先頭は前の値がないのでNaNのまま残ります。

pandas 3.0で使えなくなった書き方

import numpy as np
import pandas as pd

s = pd.Series([1, np.nan, 3])
for kw in [{"method": "pad"}, {"method": "ffill"}]:
    try:
        s.interpolate(**kw)
    except Exception as e:
        print(kw, "->", type(e).__name__ + ":", e)
try:
    pd.Series(["a", None, "c"], dtype=object).interpolate()
except Exception as e:
    print("object ->", type(e).__name__ + ":", e)
{'method': 'pad'} -> ValueError: Can not interpolate with method=pad.
{'method': 'ffill'} -> ValueError: Can not interpolate with method=ffill.
object -> TypeError: Series cannot interpolate with object dtype.
  • interpolate(method="pad")・"ffill"・"bfill"・"backfill" は pandas 3.0 で削除されました。前の値で埋めるなら ffill()、後ろの値なら bfill() を使います。
  • 文字列などobject型の列への interpolate() はエラーになります。数値に変換してから補間してください。
  • inplace=True を指定した場合、pandas 3.0 からは None ではなく変更後のオブジェクト自身が返るようになりました。

いずれもpandas 3.0.0のリリースノートに記載されています。古い記事のコードをそのまま動かしてエラーになったら、まずこの点を確認してください。

よくある質問

Q. pandasのinterpolate()は何をするメソッドですか?

欠損値(NaN)を前後の有効な値から計算して埋めるメソッドです。引数なしでは前後の値を直線で結ぶ線形補間を行い、Series・DataFrameのどちらにも使えます。DataFrameでは列ごとに補間されます。

Q. interpolate()で先頭のNaNが埋まらないのはなぜですか?

線形補間には前後両方の値が必要で、先頭のNaNには前の値がないからです。先頭も埋めたい場合は limit_direction=”both” を指定すると、直後の値で埋まります。

Q. 末尾のNaNを埋めたくない場合は?

limit_area=”inside” を指定します。前後を有効な値に挟まれたNaNだけが補間され、先頭と末尾のNaNはそのまま残ります。

Q. 時系列データの補間ではどのmethodを使えばいいですか?

インデックスが日時で間隔が一定でないなら method=”time” を使います。既定の linear は行を等間隔とみなすため、日付が飛んでいると値がずれます。

Q. interpolate(method=”ffill”) がエラーになります。

pandas 3.0 で、interpolate() の method に pad・ffill・bfill・backfill を指定する書き方は削除されました。前の値で埋めるなら ffill()、後ろの値で埋めるなら bfill() を使ってください。

まとめ

interpolate() は、欠損値を前後の値から計算して埋めるメソッドです。既定は線形補間で、先頭は埋まらず末尾は直前の値になるので、limit_direction・limit_area で埋める範囲をはっきり決めておきましょう。日付が飛ぶ時系列では method=”time”、縦に複数のグループが並ぶデータでは groupby() と組み合わせるのがポイントです。補間した値は実測値ではないので、補間した行に印を付けておくと、後の分析で区別できます。

pandas|欠損値の扱いの関連記事

NaNの判定・削除・補完など、欠損値処理に関する記事です。

pandas全体の使い方は「pandasの使い方を初心者向けに解説」でまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら