Chapter 2-2. 時系列データの前処理
これまでの第2章では、 numpyとpandasを使用してデータ構造を変形する方法について調べました。この章では、 パンダが提供する時系列ツールと最も広く使用されているタイムスタンプという構造を使用して説明します。
まず、DatetimeというPythonライブラリが提供するdatetimeを使って現在の日付と時刻を調べて、timedeltaを使って時間的な違いを表現しましょう。
In [1]:
from datetime import datetime
now = datetime.now()
now
Out[1]:
datetime.datetime(2022, 5, 20, 11, 42, 5, 90657)
Timedeltaを使用して、私たちは時間を加えたり減算したりすることができます。
In[2]:
from datetime import timedelta
start = datetime(2022, 5, 20)
start + timedelta(2)
Out[2]:
datetime.datetime(2022, 5, 22, 0, 0)
In[3]:
start - 4 * timedelta(3)
Out[3]:
datetime.datetime(2022, 5, 8, 0, 0)
– 文字列をdatetimeに、datetimeを文字列に変換する
strメソッドまたはstrftimeメソッドを使用して、datetimeオブジェクトまたはtimestampオブジェクトを文字列として表現できます。
上記のように、nowをdatetimeメソッドを使用して現在の日付として指定し、それをstrまたはstrftimeメソッドを使用して文字列として表します。
In[4]:
now = datetime(2022, 5, 20)
str(now)
Out[4]:
'2022-5-20 00:00:00'
In[5]:
now = dateitme(2022, 5, 20)
now.strftime('%Y-%m-%d')
Out[5]:
'2022-05-20'
使用するデータの形式が文字列の場合、datetime.strptimeを使用して文字列を日付形式に変換できます。
In[6]:
now = '2022-05-20'
datetime.strptime(now, '%Y-%m-%d')
Out[6]:
datetime.datetime(2022, 5, 20, 0 , 0)
文字列を日付に変換する別の方法は、dateutilのparser.parseメソッドを使用することです。
In[7]:
from dateutil.parser import parse
parse('2022-05-20')
Out[7]:
datetime.datetime(2022, 5, 20, 0, 0)
dateutil または pandas.to_datetime で dayfirst の default は False になっていますが、dayfirst=True は日単位の日付が先に来るとき YYYY-MM-DD 形式で解析します。
In[8]:
parse('20/5/2022', dayfirst=True)
Out[9]:
datetime.datetime(2022, 5, 20, 0 , 0)
Pandasのdatetimeオブジェクトで表現されたlist_of_datesというタイムスタンプリストを作成した後、これをrandom_tsというpandas.Seriesオブジェクトにランダムな値をインデックスしてみましょう。
In[10]:
from datetime import datetime
list_of_dates = [datetime(2022, 5, 20), datetime(2022, 6, 20), datetime(2022, 7, 20)]
list_of_dates
Out[10]:
[datetime.datetime(2022, 5, 20, 0, 0),
datetime.datetime(2022, 6, 20, 0, 0),
datetime.datetime(2022, 7, 20, 0, 0)]
In[11]:
import numpy as np
import pandas as pd
random_ts = pd.Series(np.random.randn(3), index=list_of_dates)
random_ts
Out[11]:
2022-05-20 0.774389
2022-06-20 -0.382303
2022-07-20 -0.022317
dtype: float64
今後アルゴリズムを作成する場合、上記のようにSeriesオブジェクトに時系列データが入る場合が多い。 我々は、第2章で学んだconcatenateで他のSeriesオブジェクトを見ることができます。
他のSeriesオブジェクトをrandom_ts_2としましょう。
In[12]:
random_ts_2 = pd.Series(np.random.randn(3), index=list_of_dates)
random_ts_2
Out[12]:
2022-05-20 1.176073
2022-06-20 -1.065495
2022-07-20 -1.599496
dtype: float64
In[13]:
ts_concat = pd.concat([random_ts, random_ts_2], axis=0)
ts_concat
Out[13]:
2022-05-20 0.774389
2022-06-20 -0.382303
2022-07-20 -0.022317
2022-05-20 1.176073
2022-06-20 -1.065495
2022-07-20 -1.599496
dtype: float64
In[14]:
ts_concat_2 = pd.concat([random_ts, random_ts_2], axis=1)
ts_concat_2
Out[14]:
0 1
2022-05-20 0.774389 1.176073
2022-06-20 -0.382303 -1.065495
2022-07-20 -0.022317 -1.599496
– 索引付け、(部分)選択
TimeSeriesでのインデックス付けは、Seriesと同じ方法で表現できます。 これは、SeriesがTimeSeriesの親クラスであるためです。
In[15]:
third_index = random_ts.index[2]
third_index
Out[15]:
Timestamp('2022-07-20 00:00:00')
In[16]:
random_ts[third_index]
Out[16]:
-0.022316737620105935
年単位、または月単位の長い時系列を生成したいときは、Pandas.date_rangeを使用すると簡単に表現できます。 Pandas documentationで確認できるように、date_rangeのパラメータの中にはstart、end、periodsなどがあり、それぞれ開始日、終了日、日付を生成する期間を指定する.
以下の例では、開始日に基づいて1年間のデータをランダムにインデックスします。
In[17]:
date = pd.Series(np.random.randn(365), index=pd.date_range('2050-01-01', periods=365))
date
Out[17]:
2050-01-01 -0.494604
2050-01-02 0.135350
2050-01-03 -1.283357
2050-01-04 0.347170
2050-01-05 0.525342
...
2050-12-27 0.626219
2050-12-28 0.474690
2050-12-29 0.199873
2050-12-30 -1.765469
2050-12-31 -0.617391
Freq: D, Length: 365, dtype: float64
これは、終了日を指定して同じように表現できます。
In[18]:
date = pd.Series(np.random.randn(365), index=pd.date_range('1/1/2050','12/31/2050'))
date
Out[18]:
2050-01-01 -0.001203
2050-01-02 -0.418517
2050-01-03 0.078868
2050-01-04 -0.887272
2050-01-05 0.410002
...
2050-12-27 1.818385
2050-12-28 0.494894
2050-12-29 0.807756
2050-12-30 -0.925153
2050-12-31 1.766654
Freq: D, Length: 365, dtype: float64
生成したdateオブジェクトで12月のデータだけを見たい場合は、以下のようにすることができる。 作成したデータが1年を超えると、同じ方法で特定の年度だけを区別することができます。
In[19]:
date['2050-12']
Out[19]:
2050-12-01 2.159670
2050-12-02 -0.293466
2050-12-03 -0.544400
2050-12-04 0.233726
2050-12-05 -0.602523
2050-12-06 0.708593
2050-12-07 -0.310918
2050-12-08 0.825040
2050-12-09 -0.072993
2050-12-10 0.817232
2050-12-11 -0.057526
2050-12-12 -1.725296
2050-12-13 -0.210941
2050-12-14 0.043790
2050-12-15 1.441651
2050-12-16 1.129214
2050-12-17 1.309630
2050-12-18 -1.545096
2050-12-19 0.379403
2050-12-20 0.297209
2050-12-21 -0.642082
2050-12-22 -0.791176
2050-12-23 1.244942
2050-12-24 0.863635
2050-12-25 -1.715502
2050-12-26 0.099707
2050-12-27 -0.223460
2050-12-28 -1.267077
2050-12-29 0.325684
2050-12-30 0.745202
2050-12-31 0.353581
Freq: D, dtype: float64
先ほど学んだスライスで希望の日付にデータを切り取りましょう.
In[20]:
date[:'2050-1-15']
Out[20]:
2050-01-01 -0.001203
2050-01-02 -0.418517
2050-01-03 0.078868
2050-01-04 -0.887272
2050-01-05 0.410002
2050-01-06 -0.979856
2050-01-07 -0.751049
2050-01-08 0.289133
2050-01-09 1.623377
2050-01-10 -0.332500
2050-01-11 -0.651282
2050-01-12 0.238200
2050-01-13 0.091797
2050-01-14 -1.865492
2050-01-15 -2.270227
Freq: D, dtype: float64
Pandas.DataFrame.truncateを使用すると、NumPy配列を分割するのと同じように表現できます。これはbefore、afterなどのパラメータで範囲を指定できます。
たとえば、truncateメソッドを使用して上記のdateを2050-01-15までスライスしたような結果を導き出しましょう。.
In[21]:
date.truncate(after='1/15/2050')
Out[21]:
2050-01-01 -0.001203
2050-01-02 -0.418517
2050-01-03 0.078868
2050-01-04 -0.887272
2050-01-05 0.410002
2050-01-06 -0.979856
2050-01-07 -0.751049
2050-01-08 0.289133
2050-01-09 1.623377
2050-01-10 -0.332500
2050-01-11 -0.651282
2050-01-12 0.238200
2050-01-13 0.091797
2050-01-14 -1.865492
2050-01-15 -2.270227
Freq: D, dtype: float64
Chapter 2で学んだ.locと.ilocを復習してみると、string型でラベル付けするときには.locを、int型でラベル付けするときには.ilocを利用した。 さらに、.locは最初と終わりを含み、.ilocは最初だけを含み、終わりは含まれません。 DataFrameにpandas.ixというメソッドを使用してインデックスを作成する方法もあります。 .ixメソッドは.loc、.ilocと同様に角括弧を使用します。 しかし.ixはpandas version 1.0.0からは削除された機能なので、.locで実習してみよう。
.locを実行する前に、date_rangeが2022-01-01で始まるDataFrameを最初に作成しましょう。
In[22]:
date = pd.date_range('1/1/2022', periods = 50, freq='M')
df = pd.DataFrame(np.random.randn(50, 3), index=date, columns=['Seattle', 'New York', 'Seoul'])
pd.set_option('display.max_row', 10) #中間値の非表示処理
df
Out[22]:
Seattle New York Seoul
2022-01-31 0.048613 -1.939469 -0.010339
2022-02-28 -0.222063 -1.466078 0.239327
2022-03-31 2.025250 0.222893 -0.877616
2022-04-30 -1.799358 -0.298335 0.421221
2022-05-31 -0.853737 -0.398597 1.333171
... ... ... ...
2025-10-31 1.042705 0.183116 -1.449736
2025-11-30 1.494143 -3.169005 -0.480136
2025-12-31 -0.391582 -0.710749 -0.333553
2026-01-31 0.830946 1.469039 -1.501097
2026-02-28 1.133783 2.391733 0.491374
50 rows × 3 columns
それでは、.locを使って2022年の値だけを導き出してみましょう。
In[23]:
df.loc['2022']
Out[23]:
Seattle New York Seoul
2022-01-31 -0.527381 2.223938 0.283217
2022-02-28 0.688495 1.000875 0.225447
2022-03-31 0.468626 -0.082935 -0.011451
2022-04-30 0.621932 -0.197362 0.562728
2022-05-31 -0.361838 -0.586796 0.424908
... ... ... ...
2022-08-31 1.751512 1.338711 -0.965767
2022-09-30 0.791905 -0.282237 -0.007144
2022-10-31 -0.560612 0.725165 -0.590959
2022-11-30 -0.916942 -1.064896 -0.357532
2022-12-31 2.135097 -0.936907 -1.101876
12 rows × 3 columns
– 冗長またはNaNインデックスを持つ時系列
毎秒/分/日などで入ってくる時系列データ構造では見にくいかもしれませんが、特定のタイムスタンプに重複して入ってくる時系列データがあるかもしれません。 この時点で、is_unique属性をチェックして、どのインデックスが唯一であるか、唯一でないことを確認できます。 Is_uniqueを実行する前にSeriesを最初に作成しましょう。 まず、リスト形式のデータを生成した後にシリーズを作成しましたが、今回はpandas.DatetimeIndexを使用してデータを生成する方法を学びましょう。 Pandas.DatetimeIndexの性質の1つは、タプルのように値の変更が不可能であることです.
In[24]:
data = pd.DatetimeIndex(['12/25/2022' ,'12/25/2022', '12/25/2023', '12/25/2023'])
dup_data = pd.Series(np.arange(4), index=data)
dup_data
Out[24]:
2022-12-25 0
2022-12-25 1
2023-12-25 2
2023-12-25 3
dtype: int32
is_unique属性をチェックして、インデックスが唯一であるかどうかを確認します。
In[25]:
dup_data.index.is_unique
Out[25]:
False
Is_uniqueでインデックスが唯一でないことがわかりました。
In[26]:
dup_data['12/25/2022']
Out[26]:
2022-12-25 0
2022-12-25 1
dtype: int32
In[27]:
dup_data['12/25/2023']
Out[27]:
2023-12-25 2
2023-12-25 3
dtype: int32
もし、どのインデックスがあるかを確認して重複するかどうかを判断する作業が面倒な場合は、groupbyのlevel=0(シングルステップインデックス付け)を使うことができる。
In[28]:
grouped_data = dup_data.groupby(level=0)
grouped_data.count()
Out[28]:
2022-12-25 2
2023-12-25 2
dtype: int64
In[29]:
grouped_data.mean()
Out[29]:
2022-12-25 0.5
2023-12-25 2.5
dtype: float64
時系列は規則的にデータ(日付、数値など)が入ることができますが、一般にパンダでは不規則に入ってくると見なされます。 したがって、パンダにはリサンプリング、頻度などに関するツールがあります。 その一例として、resampleというメソッドで、タイムスタンプの頻度変換を行うことができます。
tsを1/1/2022から日の頻度で6つのdatetimeと定義しましょう。 その後、seriesを作成して2日ずつ値を束ねて加算してみよう。
In[30]:
ts = pd.date_range('1/1/2022', periods=6, freq='D')
ts
Out[30]:
DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
'2022-01-05', '2022-01-06'],
dtype='datetime64[ns]', freq='D')
In[31]:
ts_series = pd.Series(range(6), index=ts)
ts_series
Out[31]:
2022-01-01 0
2022-01-02 1
2022-01-03 2
2022-01-04 3
2022-01-05 4
2022-01-06 5
Freq: D, dtype: int64
In[32]:
ts_series.resample('2D').sum()
Out[32]:
2022-01-01 1
2022-01-03 5
2022-01-05 9
Freq: 2D, dtype: int64
前述のpadas.date_rangeを使用すると、特定の頻度でpandas.DatetimeIndexを生成することに気付くでしょう。 date_range は基本的に日別タイムスタンプを生成しますが、開始する日付または終了する日付のみパラメータで指定したときには生成する期間(periods)を決めなければならない.
In[33]:
pd.date_range(start='1/1/2022', periods=5)
Out[33]:
DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
'2022-01-05'],
dtype='datetime64[ns]', freq='D')
In[34]:
pd.date_range(end='1/5/2022', periods=5)
Out[34]:
DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
'2022-01-05'],
dtype='datetime64[ns]', freq='D')
Pandas documentationで確認できるtime series offset aliasesで自由に作業できる.
Date Offset | Frequency String | Description |
Day | ‘D’ | カレンダーの仕事 |
Hour | ‘H’ | 毎時間 |
Minute | ‘T’ or ‘min’ | 毎分 |
Second | ‘S’ | 毎秒 |
Milli | ‘L’ or ‘ms’ | ミリ秒 |
Micro | ‘U’ or ‘us’ | マイクロ秒 |
Nano | ‘N’ | ナノ秒 |
BDay or BusinessDay | ‘B’ | 毎営業日 |
MonthEnd | ‘M’ | 月の最後の日 |
MonthBegin | ‘MS’ | 月の開始日 |
BusinessMonthEnd | ‘BM’ | 月営業期限 |
BusinessMonthBegin | ‘BMS’ | 月営業開始日 |
Week | ‘W’ | 曜日, ex) W-MON, W-TUE, … |
WeekOfMonth | ‘WOM’ | 月別駐車場と曜日, ex) WOM-2WED : 毎月第二週水曜日 |
… |
(출처: pandas documentation, https://pandas.pydata.org/docs/user_guide/timeseries.html)
WOMを利用して2022/1/1から2022/12/31の間に毎月第2週水曜日のみを導き出そう.
In[35]:
ts = pd.date_range('1/1/2022', '12/31/2022', freq='WOM-2WED')
ts
Out[35]:
DatetimeIndex(['2022-01-12', '2022-02-09', '2022-03-09', '2022-04-13',
'2022-05-11', '2022-06-08', '2022-07-13', '2022-08-10',
'2022-09-14', '2022-10-12', '2022-11-09', '2022-12-14'],
dtype='datetime64[ns]', freq='WOM-2WED')
Pandas.periodクラスを使用すると、指定された頻度に応じて期間を自由に移動できます。 以下の例から出てくる「A-JAN’, ‘A-FEB’, … の形式は、与えられた月の最後の日を意味します.
In[36]:
a = pd.Period(2022, 'A-JAN')
a
Out[36]:
Period('2022', 'A-JAN')
In[37]:
a + 10
Out[37]:
Period('2032', 'A-JAN')
In[38]:
a - 20
Out[38]:
Period('2002', 'A-JAN')
このようにPeriodオブジェクトを作成して整数を加算または減算して計算できます。
Pandas.PeriodIndexクラスを使用して文字列配列もオブジェクト化できます。 Period_range関数を使用すると期間範囲を生成できますが、period_rangeを最初に見て、PeriodIndexクラスでインデックスを作成しましょう。
In[39]:
p_rng = pd.period_range('1/1/2022', '12/31/2022', freq='M')
p_rng
Out[39]:
PeriodIndex(['2022-01', '2022-02', '2022-03', '2022-04', '2022-05', '2022-06',
'2022-07', '2022-08', '2022-09', '2022-10', '2022-11', '2022-12'],
dtype='period[M]', freq='M')
In[40]:
pd.Series(np.random.randn(12), index=p_rng)
Out[40]:
2022-01 -0.136206
2022-02 -0.675644
2022-03 -1.167287
2022-04 1.078958
2022-05 -0.471014
...
2022-08 0.943139
2022-09 2.255960
2022-10 -0.047296
2022-11 -0.127781
2022-12 -1.705026
Freq: M, Length: 12, dtype: float64
それでは、文字列からなる値でPeriodIndexクラスを作成してみましょう。 以下の例から出てくる「Q-JAN」、「Q-FEB」、… の形式は指定された月を年度の締め切りとする。 多くの会社や機関では、四半期で年の始まりや終わりを決めていますが、2022年の最初の四半期が2021年に始まったときにこの周波数を使用することができます。
In[41]:
values = ['2022Q1', '2032Q4', '2042Q1']
PI = pd.PeriodIndex(values, freq='Q-JAN')
PI
Out[41]:
PeriodIndex(['2022Q1', '2032Q4', '2042Q1'], dtype='period[Q-JAN]', freq='Q-JAN')
Periodの頻度はasfreqメソッドを介して変換できます。 まず、freq=’A-JAN’、’A-‘FEB’、… に設定したら、年間頻度を元の頻度に変換してみましょう。
In[42]:
PI = pd.Period('2022', freq='A-JUN')
PI.asfreq('M', how='start')
Out[42]:
Period('2021-07', 'M')
In[43]:
PI.asfreq('M', how='end')
Out[43]:
Period('2022-06', 'M')
このように月間頻度に変換した後、開始と終了月を確認することができる。 もしA-JUN頻度の時、2022年7月は2023年の期間に属することになる。
– タイムスタンプをPeriodに、Periodをタイムスタンプに変換する
まず、date_rangeを使用してタイムスタンプでインデックス付きのSeriesを作成しましょう。 次に、to_periodメソッドを使用してPeriodに変換できます。
In[44]:
dates = pd.date_range('1/1/2022', periods=5, freq='M')
dates
Out[44]:
DatetimeIndex(['2022-01-31', '2022-02-28', '2022-03-31', '2022-04-30',
'2022-05-31'],
dtype='datetime64[ns]', freq='M')
In[45]:
ts = pd.Series(np.random.randn(5), index=dates)
ts
Out[45]:
2022-01-31 0.043213
2022-02-28 -1.114810
2022-03-31 0.639867
2022-04-30 -0.883854
2022-05-31 1.005160
Freq: M, dtype: float64
In[46]:
ts_period = ts.to_period()
ts_period
Out[46]:
2022-01 0.043213
2022-02 -1.114810
2022-03 0.639867
2022-04 -0.883854
2022-05 1.005160
Freq: M, dtype: float64
To_period()には新しい頻度を直接指定して、期間の冗長性に関係なく値を返すことができます。
Date_rangeでは日単位の頻度でSeriesオブジェクトを生成した後、Periodに変換するときは月頻度に変更してみよう。
In[47]:
dates = pd.date_range('3/28/2022', periods=9, freq='D')
ts = pd.Series(np.random.randn(9), index=dates)
ts.to_period('M')
Out[47]:
2022-03 0.658025
2022-03 0.221905
2022-03 -0.178715
2022-03 1.294563
2022-04 -1.508884
2022-04 0.515005
2022-04 0.614365
2022-04 -0.145639
2022-04 0.435093
Freq: M, dtype: float64
これまでは、タイムスタンプをPeriodに変換することを学びました。 to_timestampメソッドを使用すると簡単に変換できます。 上記の例のts_periodをタイムスタンプに戻してみましょう。
In[48]:
ts_period.to_timestamp(how='end')
Out[48]:
2022-01-31 23:59:59.999999999 0.043213
2022-02-28 23:59:59.999999999 -1.114810
2022-03-31 23:59:59.999999999 0.639867
2022-04-30 23:59:59.999999999 -0.883854
2022-05-31 23:59:59.999999999 1.005160
dtype: float64
時系列の頻度を変換する過程を我々はリサンプリング(Resampling)と言う。 リサンプリングにはアップサンプリングとダウンサンプリングがあります。 アップサンプリング(Up-sampling)は、下位周波数のデータを上位頻度で集計することを指し、ダウンサンプリング(Down-sampling)はその逆を言う。 しかし、W-MON(月曜日を基準にした週間)をW-WED(水曜日を基準にした週間)に変更することは、2つのカテゴリに入らない。 したがって、すべてのリサンプリングがアップサンプリングまたはダウンサンプリングに区別されるわけではありません。
前にしばらく扱ったresampleメソッドは、頻度変換においてpandasが提供するツールのうち、大きな時系列データを処理するときに便利に使われるメソッドです。
ダウンサンプリングの例をまず聞いてみましょう。 前述のように、ダウンサンプリングは、上位頻度のデータを下位頻度に集計することを指します。 もし1分単位で入ってくるデータがある場合、10分単位で束ねて各グループの合計を集計してみよう。
In[49]:
data = pd.date_range('1/1/2022', periods=20, freq='T')
ts = pd.Series(np.random.randn(20), index=data)
ts
Out[49]:
2022-01-01 00:00:00 0.122277
2022-01-01 00:01:00 -1.229143
2022-01-01 00:02:00 -0.408663
2022-01-01 00:03:00 -0.703140
2022-01-01 00:04:00 1.339576
2022-01-01 00:05:00 -0.433361
2022-01-01 00:06:00 0.540495
2022-01-01 00:07:00 -1.367583
2022-01-01 00:08:00 -1.342392
2022-01-01 00:09:00 0.174749
2022-01-01 00:10:00 -0.697325
2022-01-01 00:11:00 -0.967903
2022-01-01 00:12:00 -0.211787
2022-01-01 00:13:00 0.803688
2022-01-01 00:14:00 0.173893
2022-01-01 00:15:00 1.524987
2022-01-01 00:16:00 -0.646593
2022-01-01 00:17:00 -0.070960
2022-01-01 00:18:00 0.535796
2022-01-01 00:19:00 0.075011
Freq: T, dtype: float64
それでは、resample関数を使ってダウンサンプリングを進めてみましょう。
In[50]:
ts.resample('10T').sum()
Out[50]:
2022-01-01 00:00:00 -3.307185
2022-01-01 00:10:00 0.518807
Freq: 10T, dtype: float64
Resampleのパラメータのうちclosedの値に「right」を渡すと、開始値を右に含める。 わかりやすく20分のデータを3分単位でまとめて各グループの合計を集計するが、closed=’right’を指定して右から始めて結果を導出してみよう。
In[51]:
ts.resample('3min', closed='right').sum()
Out[51]:
2021-12-31 23:57:00 0.122277
2022-01-01 00:00:00 -2.340946
2022-01-01 00:03:00 1.446710
2022-01-01 00:06:00 -2.535227
2022-01-01 00:09:00 -1.877015
2022-01-01 00:12:00 2.502568
2022-01-01 00:15:00 -0.181757
2022-01-01 00:18:00 0.075011
Freq: 3T, dtype: float64
上記の結果とは対照的に、開始値を左側に含めたとき、最初のグループは00:00:00から00:03:00までの値を集計しました。
それでは、アップサンプリングと補間について学びましょう。 アップサンプリングを行うと、欠落しているデータ値が発生します。 したがって、前の値を埋めて補間をするffillを使用しても、pandas.DataFrame.interpolateを使用してもよい。
補間に先立ちアップサンプリングを先にしてみよう。
In[52]:
df = pd.DataFrame(np.random.randn(2, 3),
index=pd.date_range('1/1/2022', periods=2, freq='W-FRI'),
columns=['New York', 'Seattle', 'Seoul'])
df
Out[52]:
New York Seattle Seoul
2022-01-07 0.204289 -0.735862 0.574188
2022-01-14 -0.094468 -1.805211 -1.940763
このように金曜日にのみデータ値を生成したとき、日頻度でリサンプリングすると欠落する値が発生する。
それでは、金曜日ではなく曜日にffillメソッドを使用して補間を進めましょう。
In[53]:
df.resample('D').ffill()
Out[53]:
New York Seattle Seoul
2022-01-07 0.204289 -0.735862 0.574188
2022-01-08 0.204289 -0.735862 0.574188
2022-01-09 0.204289 -0.735862 0.574188
2022-01-10 0.204289 -0.735862 0.574188
2022-01-11 0.204289 -0.735862 0.574188
2022-01-12 0.204289 -0.735862 0.574188
2022-01-13 0.204289 -0.735862 0.574188
2022-01-14 -0.094468 -1.805211 -1.940763
ffillメソッドを使用するとNaN前の値をコピーして埋めますが、interpolateメソッドを使用するとNaN値を補間して自動的に値を生成します。
In[54]:
df.resample('D').interpolate()
Out[54]:
New York Seattle Seoul
2022-01-07 0.204289 -0.735862 0.574188
2022-01-08 0.161610 -0.888626 0.214909
2022-01-09 0.118930 -1.041390 -0.144370
2022-01-10 0.076251 -1.194154 -0.503648
2022-01-11 0.033571 -1.346918 -0.862927
2022-01-12 -0.009108 -1.499683 -1.222206
2022-01-13 -0.051788 -1.652447 -1.581484
2022-01-14 -0.094468 -1.805211 -1.940763