はじめに
分析エンジニアがよく利用するpythonのpandasライブラリ。
分析業務を行わないソフトウェアエンジニアでも、システムを結合する際にどうしても利用しなければならない場面があります。
でも前に使ったの半年前なんですよねー。。。なんで言うこと聞いてくれないのですかDataFrameさん。
ということで今回は、とあるDataFrameに対して線形補完を行うと以下のエラーが発生しました。
1時間毎の時系列データを30分毎のデータに変換し、線形補間しようとしています。
>>> df.asfreq('30min')
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.17942 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 00:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 01:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.79156 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 03:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 04:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 05:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.86707 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 06:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 07:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 08:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.64967 0.000000 0.0 0.0000 0.000000 NaN
>>> df.asfreq('30min').interpolate(method='linear')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/generic.py", line 7064, in interpolate
**kwargs
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/managers.py", line 569, in interpolate
return self.apply("interpolate", **kwargs)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/managers.py", line 438, in apply
applied = getattr(b, f)(**kwargs)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/blocks.py", line 1965, in interpolate
values=values.fillna(value=fill_value, method=method, limit=limit),
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/arrays/datetimelike.py", line 777, in fillna
value, method = validate_fillna_kwargs(value, method)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/util/_validators.py", line 360, in validate_fillna_kwargs
method = clean_fill_method(method)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/missing.py", line 96, in clean_fill_method
raise ValueError(msg)
ValueError: Invalid fill method. Expecting pad (ffill) or backfill (bfill). Got linear
調査を進めるとどうやらtimezone情報を持つdatetime64型のカラムを含む場合に問題が起きるようでした。
githubにも同様の内容でissueが上がっていましたが、現時点では解決していないようです。
ライブラリのコアな部分の設定を上書きするとエラーを無視できるようになるというようなイメージのおまじないを使うようですが、詳しくは追っていません。
(ちなみにこのおまじないは有効でした。それはそれで気になる。。。)
ただよくわからないおまじないを使って対処するわけにはいかないので、もう少しわかりやすい対処を考えてみました。
もしより良い方法をご存知の方いらっしゃったら、是非教えて下さい。
検証環境
- python: 3.7.4
- pandas: 0.25.3
検証に利用したデータ
検証には気象予報データを利用しました。
検証に必須ではないデータも多々ありますが、より具体的なデータの例としてこちらを用いました。
>>> df
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.17942 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.79156 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.86707 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.64967 0.000000 0.0 0.0000 0.000000 NaN
参考までに各カラムは以下のようなデータです。
- target_datetime: 予報の対象時刻
- forecasted_at: 予報が作られた時刻
- temperature: 気温
- tcdc: 全雲量
- hcdc: 高層雲量
- mcdc: 中層雲量
- lcdc: 低層雲量
- dsrf: 日射量
>>> df.index
DatetimeIndex(['2019-11-29 00:00:00+09:00', '2019-11-29 01:00:00+09:00',
'2019-11-29 02:00:00+09:00', '2019-11-29 03:00:00+09:00',
'2019-11-29 04:00:00+09:00', '2019-11-29 05:00:00+09:00',
'2019-11-29 06:00:00+09:00', '2019-11-29 07:00:00+09:00',
'2019-11-29 08:00:00+09:00', '2019-11-29 09:00:00+09:00'],
dtype='datetime64[ns, pytz.FixedOffset(540)]', name='target_datetime', freq=None)
>>> df.dtypes
forecasted_at datetime64[ns, pytz.FixedOffset(540)]
temperature float64
tcdc float64
hcdc float64
mcdc float64
lcdc float64
dsrf float64
dtype: object
失敗パターン特定
timezoneを含むカラムに問題がありそうということはわかりましたが、インデックスのデータもtimezoneを含んでいます。
まずはtimezoneを含まないカラムのみのDataFrameに対して線形補完を行ってみます。
>>> df.asfreq('30min').loc[:, ['temperature']]
temperature
target_datetime
2019-11-29 00:00:00+09:00 5.17942
2019-11-29 00:30:00+09:00 NaN
2019-11-29 01:00:00+09:00 4.38748
2019-11-29 01:30:00+09:00 NaN
2019-11-29 02:00:00+09:00 3.87086
2019-11-29 02:30:00+09:00 NaN
2019-11-29 03:00:00+09:00 3.79156
2019-11-29 03:30:00+09:00 NaN
2019-11-29 04:00:00+09:00 3.14681
2019-11-29 04:30:00+09:00 NaN
2019-11-29 05:00:00+09:00 2.67394
2019-11-29 05:30:00+09:00 NaN
2019-11-29 06:00:00+09:00 2.86707
2019-11-29 06:30:00+09:00 NaN
2019-11-29 07:00:00+09:00 2.38549
2019-11-29 07:30:00+09:00 NaN
2019-11-29 08:00:00+09:00 3.01866
2019-11-29 08:30:00+09:00 NaN
2019-11-29 09:00:00+09:00 4.64967
>>> df.asfreq('30min').loc[:, ['temperature']].interpolate(method='linear')
temperature
target_datetime
2019-11-29 00:00:00+09:00 5.179420
2019-11-29 00:30:00+09:00 4.783450
2019-11-29 01:00:00+09:00 4.387480
2019-11-29 01:30:00+09:00 4.129170
2019-11-29 02:00:00+09:00 3.870860
2019-11-29 02:30:00+09:00 3.831210
2019-11-29 03:00:00+09:00 3.791560
2019-11-29 03:30:00+09:00 3.469185
2019-11-29 04:00:00+09:00 3.146810
2019-11-29 04:30:00+09:00 2.910375
2019-11-29 05:00:00+09:00 2.673940
2019-11-29 05:30:00+09:00 2.770505
2019-11-29 06:00:00+09:00 2.867070
2019-11-29 06:30:00+09:00 2.626280
2019-11-29 07:00:00+09:00 2.385490
2019-11-29 07:30:00+09:00 2.702075
2019-11-29 08:00:00+09:00 3.018660
2019-11-29 08:30:00+09:00 3.834165
2019-11-29 09:00:00+09:00 4.649670
問題なさそうです。やはり問題はインデックスではなく、カラムにtimezone情報が含まれていることのようです。
念のためtimezone情報を含むカラムが問題になっていることを確認します。
>>> df.asfreq('30min').loc[:, ['forecasted_at']]
forecasted_at
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00
2019-11-29 00:30:00+09:00 NaT
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00
2019-11-29 01:30:00+09:00 NaT
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00
2019-11-29 02:30:00+09:00 NaT
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00
2019-11-29 03:30:00+09:00 NaT
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00
2019-11-29 04:30:00+09:00 NaT
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00
2019-11-29 05:30:00+09:00 NaT
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00
2019-11-29 06:30:00+09:00 NaT
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00
2019-11-29 07:30:00+09:00 NaT
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00
2019-11-29 08:30:00+09:00 NaT
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00
>>> df.asfreq('30min').loc[:, ['forecasted_at']].interpolate(method='linear')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/generic.py", line 7064, in interpolate
**kwargs
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/managers.py", line 569, in interpolate
return self.apply("interpolate", **kwargs)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/managers.py", line 438, in apply
applied = getattr(b, f)(**kwargs)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/internals/blocks.py", line 1965, in interpolate
values=values.fillna(value=fill_value, method=method, limit=limit),
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/arrays/datetimelike.py", line 777, in fillna
value, method = validate_fillna_kwargs(value, method)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/util/_validators.py", line 360, in validate_fillna_kwargs
method = clean_fill_method(method)
File "/Users/hoge/.local/share/virtualenvs/myproject-RpjxRXLN/lib/python3.7/site-packages/pandas/core/missing.py", line 96, in clean_fill_method
raise ValueError(msg)
ValueError: Invalid fill method. Expecting pad (ffill) or backfill (bfill). Got linear
再現しました。
ここまでくれば何とかなりそうです。
解決方法
方法1: カラム毎に処理を分割して最後に結合する
線形補完できないカラムが混じっていることが問題なので、
線形補完できないカラムのDataFrameとできるカラムのDataFrameに分離し、できるカラムのDataFrameに対してのみ線形補完を行い、最後に結合します。
まずはどちらも補完せずに結合できることを確認します。
Indexをキーにして結合する場合はjoinメソッドを使います。
>>> pd.DataFrame.join(df.loc[:, ['forecasted_at']].asfreq('30min'), df.loc[:, ['temperature', 'dsrf']].asfreq('30min'))
forecasted_at temperature dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.17942 NaN
2019-11-29 00:30:00+09:00 NaT NaN NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.00000
2019-11-29 01:30:00+09:00 NaT NaN NaN
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.00000
2019-11-29 02:30:00+09:00 NaT NaN NaN
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.79156 NaN
2019-11-29 03:30:00+09:00 NaT NaN NaN
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.00000
2019-11-29 04:30:00+09:00 NaT NaN NaN
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.00000
2019-11-29 05:30:00+09:00 NaT NaN NaN
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.86707 NaN
2019-11-29 06:30:00+09:00 NaT NaN NaN
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.38549 7.96875
2019-11-29 07:30:00+09:00 NaT NaN NaN
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.01866 128.75000
2019-11-29 08:30:00+09:00 NaT NaN NaN
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.64967 NaN
今度は数値カラムのDataFrame側のみ線形補完して結合します。
>>> pd.DataFrame.join(df.loc[:, ['forecasted_at']].asfreq('30min'), df.loc[:, ['temperature', 'dsrf']].asfreq('30min').interpolate(method='linear'))
forecasted_at temperature dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.179420 NaN
2019-11-29 00:30:00+09:00 NaT 4.783450 NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.387480 0.000000
2019-11-29 01:30:00+09:00 NaT 4.129170 0.000000
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.870860 0.000000
2019-11-29 02:30:00+09:00 NaT 3.831210 0.000000
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.791560 0.000000
2019-11-29 03:30:00+09:00 NaT 3.469185 0.000000
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.146810 0.000000
2019-11-29 04:30:00+09:00 NaT 2.910375 0.000000
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.673940 0.000000
2019-11-29 05:30:00+09:00 NaT 2.770505 1.992188
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.867070 3.984375
2019-11-29 06:30:00+09:00 NaT 2.626280 5.976562
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.385490 7.968750
2019-11-29 07:30:00+09:00 NaT 2.702075 68.359375
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.018660 128.750000
2019-11-29 08:30:00+09:00 NaT 3.834165 128.750000
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.649670 128.750000
見事結合できました!
方法2: timezoneを含むdatetime64カラムからtimezone情報を削除したDataFrameを用意する
timezoneが問題なのであれば、それを削除すればいいですよね。
カラムの型変換には汎用的な処理が行えるapplyメソッドを利用しました。
(to_xxxxみたいなメソッドがあることを期待しましたがありませんでした。。。)
まずはカラム(Series)に対してapplyできることを確認します。
>>> df.forecasted_at.apply(lambda d: d.replace(tzinfo=None))
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00
Name: forecasted_at, dtype: datetime64[ns]
うまく変換できたので、カラム情報を上書きし、カラムのデータタイプを確認します。
>>> df.forecasted_at = df.forecasted_at.apply(lambda d: d.replace(tzinfo=None))
>>> df.dtypes
forecasted_at datetime64[ns]
temperature float64
tcdc float64
hcdc float64
mcdc float64
lcdc float64
dsrf float64
dtype: object
中身をみてもtimezone情報は消えていることがわかります。
>>> df.asfreq('30min')
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00 5.17942 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 00:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 01:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00 3.79156 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 03:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 04:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 05:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00 2.86707 0.000000 0.0 0.0000 0.000000 NaN
2019-11-29 06:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 07:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 08:30:00+09:00 NaT NaN NaN NaN NaN NaN NaN
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00 4.64967 0.000000 0.0 0.0000 0.000000 NaN
準備は整いました。線形補完します。
>>> df.asfreq('30min').interpolate(method='linear')
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00 5.179420 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 00:30:00+09:00 NaT 4.783450 0.000000 0.0 12.1582 12.158200 NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00 4.387480 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 01:30:00+09:00 NaT 4.129170 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00 3.870860 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 02:30:00+09:00 NaT 3.831210 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00 3.791560 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 03:30:00+09:00 NaT 3.469185 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00 3.146810 0.000000 0.0 0.0000 0.000000 0.000000
2019-11-29 04:30:00+09:00 NaT 2.910375 0.439453 0.0 0.0000 0.439453 0.000000
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00 2.673940 0.878906 0.0 0.0000 0.878906 0.000000
2019-11-29 05:30:00+09:00 NaT 2.770505 0.439453 0.0 0.0000 0.439453 1.992188
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00 2.867070 0.000000 0.0 0.0000 0.000000 3.984375
2019-11-29 06:30:00+09:00 NaT 2.626280 0.000000 0.0 0.0000 0.000000 5.976562
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00 2.385490 0.000000 0.0 0.0000 0.000000 7.968750
2019-11-29 07:30:00+09:00 NaT 2.702075 0.000000 0.0 0.0000 0.000000 68.359375
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00 3.018660 0.000000 0.0 0.0000 0.000000 128.750000
2019-11-29 08:30:00+09:00 NaT 3.834165 0.000000 0.0 0.0000 0.000000 128.750000
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00 4.649670 0.000000 0.0 0.0000 0.000000 128.750000
見事線形補完できました!
ただしエラーはでないもののdatetime64型は線形補完できないようです。
おわりに
datetime64型の時刻を表す情報としてはただの数値(エポック秒)だと思うのですが線形補完できない理由があるのでしょうか。
モヤモヤしますが謎解きはまた時間のある時にしたいと思います。
付録
補完関連のメソッドの動作確認
時刻情報のカラムに対して線形補完するのは、単なる数値カラムに対して行うよりは複雑な事情があるのかもしれません。
でも前後の値を利用して、同じ値を補完するffillやbfillなら問題ないのでは?と考えて、適用してみました。
>>> df.asfreq('30min').interpolate(method='ffill')
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.17942 0.000000 0.0 24.3164 24.316400 24.31640
2019-11-29 00:30:00+09:00 2019-11-29 00:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 01:30:00+09:00 2019-11-29 00:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:30:00+09:00 2019-11-29 00:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.79156 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 03:30:00+09:00 2019-11-29 03:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 04:30:00+09:00 2019-11-29 03:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 05:30:00+09:00 2019-11-29 03:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.86707 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 06:30:00+09:00 2019-11-29 06:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 07:30:00+09:00 2019-11-29 06:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 08:30:00+09:00 2019-11-29 06:00:00+09:00 NaN NaN NaN NaN NaN NaN
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.64967 0.000000 0.0 0.0000 0.000000 0.00000
forecasted_atは補完できましたが、なぜか数値カラムは補完できませんでした。
調べてみるとinterpolateメソッドとは別にパディング系のメソッドが用意されていることがわかりました。
早速その1つであるffillメソッドで補完してみます。
>>> df.asfreq('30min').ffill()
forecasted_at temperature tcdc hcdc mcdc lcdc dsrf
target_datetime
2019-11-29 00:00:00+09:00 2019-11-29 00:00:00+09:00 5.17942 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 00:30:00+09:00 2019-11-29 00:00:00+09:00 5.17942 0.000000 0.0 24.3164 24.316400 NaN
2019-11-29 01:00:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 01:30:00+09:00 2019-11-29 00:00:00+09:00 4.38748 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:00:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 02:30:00+09:00 2019-11-29 00:00:00+09:00 3.87086 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 03:00:00+09:00 2019-11-29 03:00:00+09:00 3.79156 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 03:30:00+09:00 2019-11-29 03:00:00+09:00 3.79156 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 04:00:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 04:30:00+09:00 2019-11-29 03:00:00+09:00 3.14681 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 05:00:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 05:30:00+09:00 2019-11-29 03:00:00+09:00 2.67394 0.878906 0.0 0.0000 0.878906 0.00000
2019-11-29 06:00:00+09:00 2019-11-29 06:00:00+09:00 2.86707 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 06:30:00+09:00 2019-11-29 06:00:00+09:00 2.86707 0.000000 0.0 0.0000 0.000000 0.00000
2019-11-29 07:00:00+09:00 2019-11-29 06:00:00+09:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 07:30:00+09:00 2019-11-29 06:00:00+09:00 2.38549 0.000000 0.0 0.0000 0.000000 7.96875
2019-11-29 08:00:00+09:00 2019-11-29 06:00:00+09:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 08:30:00+09:00 2019-11-29 06:00:00+09:00 3.01866 0.000000 0.0 0.0000 0.000000 128.75000
2019-11-29 09:00:00+09:00 2019-11-29 09:00:00+09:00 4.64967 0.000000 0.0 0.0000 0.000000 128.75000
全てのカラムを補完できました。。。何故なんだ。。。
線形補完はできないものの、パディングしたいだけであれば、interpolateメソッドよりも有用そうです。
DataFrame初心者には理解できない挙動ですが、今掘り下げる時間はありません。
謎は深まるばかりです。