時系列データの処理
Contents
時系列データの処理#
本節ではpandasを利用して時系列データを処理する方法を学びます。
サンプルデータとして、厚生労働省の 新型コロナウイルス感染症 オープンデータ データを利用します。
read_csv
メソッドの引数 parse_dates
に渡した列名は datetime64[ns]
型として処理されます。
import pandas as pd
import plotly.express as px
df = pd.read_csv(
"https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv",
parse_dates=["Date"],
)
df.head()
Date | ALL | Hokkaido | Aomori | Iwate | Miyagi | Akita | Yamagata | Fukushima | Ibaraki | ... | Ehime | Kochi | Fukuoka | Saga | Nagasaki | Kumamoto | Oita | Miyazaki | Kagoshima | Okinawa | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-01-16 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 2020-01-17 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 2020-01-18 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 2020-01-19 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 2020-01-20 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 49 columns
df.dtypes[:5]
Date datetime64[ns]
ALL int64
Hokkaido int64
Aomori int64
Iwate int64
dtype: object
date = df.loc[:, "Date"]
type(date.dt)
pandas.core.indexes.accessors.DatetimeProperties
.dtアクセサ#
Series
には「.dtアクセサ」と呼ばれる datetime
型の要素を操作できる機能があります。
https://pandas.pydata.org/pandas-docs/stable/reference/series.html#datetimelike-properties
date = df.loc[:, "Date"]
type(date.dt)
pandas.core.indexes.accessors.DatetimeProperties
month
属性では「月」を取得できます。
date.dt.month
0 1
1 1
2 1
3 1
4 1
..
1034 11
1035 11
1036 11
1037 11
1038 11
Name: Date, Length: 1039, dtype: int64
練習問題1#
date
オブジェクトから曜日名を取得してください。
# 解答セル
DatetimeIndex#
DatetimeIndex
は時系列データに特化したインデックスです。さまざまな方法で要素にアクセスできます。
df.set_index("Date", inplace=True)
df.head()
ALL | Hokkaido | Aomori | Iwate | Miyagi | Akita | Yamagata | Fukushima | Ibaraki | Tochigi | ... | Ehime | Kochi | Fukuoka | Saga | Nagasaki | Kumamoto | Oita | Miyazaki | Kagoshima | Okinawa | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||
2020-01-16 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-01-17 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-01-18 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-01-19 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-01-20 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 48 columns
df.index
DatetimeIndex(['2020-01-16', '2020-01-17', '2020-01-18', '2020-01-19',
'2020-01-20', '2020-01-21', '2020-01-22', '2020-01-23',
'2020-01-24', '2020-01-25',
...
'2022-11-10', '2022-11-11', '2022-11-12', '2022-11-13',
'2022-11-14', '2022-11-15', '2022-11-16', '2022-11-17',
'2022-11-18', '2022-11-19'],
dtype='datetime64[ns]', name='Date', length=1039, freq=None)
loc
に datetime
型や文字列を指定できます。次のように文字列で指定できます。
df.loc["2020-02"]
ALL | Hokkaido | Aomori | Iwate | Miyagi | Akita | Yamagata | Fukushima | Ibaraki | Tochigi | ... | Ehime | Kochi | Fukuoka | Saga | Nagasaki | Kumamoto | Oita | Miyazaki | Kagoshima | Okinawa | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||
2020-02-01 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-02 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-03 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-04 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-05 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-06 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-07 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-08 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-09 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-11 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-12 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-13 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-14 | 5 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2020-02-15 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-16 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-17 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-18 | 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-19 | 9 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2020-02-20 | 8 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2020-02-21 | 13 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-22 | 23 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | ... | 0 | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 0 |
2020-02-23 | 10 | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-24 | 16 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-25 | 8 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
2020-02-26 | 22 | 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-27 | 24 | 15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-28 | 19 | 12 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2020-02-29 | 9 | 4 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
29 rows × 48 columns
df.loc["2020-12":"2021-01"]
ALL | Hokkaido | Aomori | Iwate | Miyagi | Akita | Yamagata | Fukushima | Ibaraki | Tochigi | ... | Ehime | Kochi | Fukuoka | Saga | Nagasaki | Kumamoto | Oita | Miyazaki | Kagoshima | Okinawa | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||||||||||
2020-12-01 | 2014 | 206 | 4 | 10 | 11 | 0 | 3 | 0 | 50 | 26 | ... | 5 | 5 | 33 | 10 | 2 | 18 | 14 | 10 | 3 | 27 |
2020-12-02 | 2419 | 176 | 8 | 4 | 9 | 0 | 4 | 5 | 44 | 24 | ... | 7 | 8 | 42 | 6 | 0 | 11 | 15 | 8 | 5 | 46 |
2020-12-03 | 2505 | 206 | 8 | 4 | 21 | 0 | 7 | 3 | 37 | 14 | ... | 5 | 15 | 31 | 4 | 0 | 8 | 18 | 7 | 11 | 49 |
2020-12-04 | 2435 | 212 | 6 | 1 | 21 | 0 | 3 | 6 | 85 | 17 | ... | 7 | 16 | 45 | 4 | 0 | 15 | 18 | 9 | 5 | 47 |
2020-12-05 | 2496 | 183 | 3 | 7 | 21 | 0 | 6 | 13 | 31 | 13 | ... | 2 | 19 | 42 | 3 | 0 | 8 | 18 | 8 | 6 | 41 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2021-01-27 | 3968 | 147 | 4 | 6 | 27 | 2 | 10 | 25 | 84 | 38 | ... | 15 | 1 | 185 | 7 | 11 | 22 | 14 | 17 | 10 | 131 |
2021-01-28 | 4122 | 115 | 4 | 0 | 27 | 2 | 7 | 15 | 60 | 34 | ... | 1 | 6 | 185 | 7 | 28 | 15 | 22 | 17 | 13 | 96 |
2021-01-29 | 3547 | 111 | 3 | 0 | 13 | 5 | 15 | 14 | 86 | 44 | ... | 8 | 6 | 159 | 2 | 18 | 19 | 20 | 14 | 19 | 63 |
2021-01-30 | 3330 | 106 | 9 | 1 | 23 | 0 | 6 | 11 | 69 | 24 | ... | 16 | 5 | 154 | 6 | 30 | 13 | 10 | 5 | 11 | 76 |
2021-01-31 | 2673 | 104 | 6 | 0 | 17 | 1 | 2 | 9 | 63 | 16 | ... | 0 | 1 | 127 | 5 | 4 | 8 | 13 | 11 | 13 | 39 |
62 rows × 48 columns
練習問題2#
df
オブジェクトから2021年以降のデータを抽出してください。
# 解答セル
区間・期間の集計#
「ALL」列をSeriesとして取得します。
all_prefs = df.loc[:, "ALL"]
all_prefs.head()
Date
2020-01-16 1
2020-01-17 0
2020-01-18 0
2020-01-19 0
2020-01-20 0
Name: ALL, dtype: int64
resample
メソッドを実行することで、データをリサンプリングできます。次のコードでは7日ごとの移動平均を算出しています。
resample
メソッドの引数には頻度(年、月など)を示す文字列を渡します。指定できる文字列はpandasの User Guide を参照してください。
all_prefs.resample("7D").mean()
Date
2020-01-16 0.142857
2020-01-23 1.000000
2020-01-30 1.000000
2020-02-06 0.285714
2020-02-13 5.142857
...
2022-10-20 35406.428571
2022-10-27 46532.000000
2022-11-03 63376.142857
2022-11-10 78420.857143
2022-11-17 89089.000000
Freq: 7D, Name: ALL, Length: 149, dtype: float64
resample
メソッドの引数を"1W"
(1週間)で渡した場合は日曜日を基準に算出します。
all_prefs.resample("1W").mean()
Date
2020-01-19 0.250000
2020-01-26 0.428571
2020-02-02 1.142857
2020-02-09 0.428571
2020-02-16 2.142857
...
2022-10-23 33450.428571
2022-10-30 40330.285714
2022-11-06 57328.571429
2022-11-13 71728.000000
2022-11-20 85812.833333
Freq: W-SUN, Name: ALL, Length: 149, dtype: float64
all_prefs.resample("1W").first()
Date
2020-01-19 1
2020-01-26 0
2020-02-02 0
2020-02-09 0
2020-02-16 0
...
2022-10-23 15395
2022-10-30 16851
2022-11-06 22415
2022-11-13 31703
2022-11-20 37595
Freq: W-SUN, Name: ALL, Length: 149, dtype: int64
データを可視化することで、時系列の推移を視覚的に把握できるようになります。移動平均を算出することで、時系列データのトレンドが把握しやすくなったことがわかります。可視化方法については次章で解説します。
px.line(all_prefs, title="新規陽性者数の推移")