pandas.DataFrame, Seriesを時系列データとして処理
pandas.DataFrame
, pandas.Series
のインデックスをdatetime64[ns]
型にするとDatetimeIndex
とみなされ、時系列データを処理する様々な機能が使えるようになる。
年や月で行を指定したりスライスで期間を抽出したりできるので、日付や時刻など日時の情報が入ったデータを処理する場合は便利。
例えば、曜日や年、月ごとの合計や平均を算出するのも簡単にできるようになる。
ここでは、
- 既存データの列を
DatetimeIndex
として指定する方法 - CSV読み込み時に
DatetimeIndex
を指定する方法 pandas.Series
の場合
について説明する。
例として以下のcsvデータを使う。
文字列とdatetime64[ns]
型との相互変換、年月日、時刻を数値として抽出する方法などについては以下の記事を参照。
また、タイムゾーンの扱いについては以下の記事を参照。
既存データの列をDatetimeIndexとして指定
デフォルトの0
始まりのインデックスと日付の文字列の列を持つpandas.DataFrame
を例とする。
import pandas as pd
df = pd.read_csv('data/src/sample_date.csv')
print(df)
# date val_1 val_2
# 0 2017-11-01 65 76
# 1 2017-11-07 26 66
# 2 2017-11-18 47 47
# 3 2017-11-27 20 38
# 4 2017-12-05 65 85
# 5 2017-12-12 4 29
# 6 2017-12-22 31 54
# 7 2017-12-29 21 8
# 8 2018-01-03 98 76
# 9 2018-01-08 48 64
# 10 2018-01-19 18 48
# 11 2018-01-23 86 70
print(type(df.index))
# <class 'pandas.core.indexes.range.RangeIndex'>
print(df['date'].dtype)
# object
日付の文字列の列に対してto_datetime()
を適用し、datetime64[ns]
型に変換する。
df['date'] = pd.to_datetime(df['date'])
print(df['date'].dtype)
# datetime64[ns]
set_index()
メソッドでdatetime64[ns]
型の列をインデックスに指定する。
これでインデックスがDatetimeIndex
となる。インデックスの各要素はTimestamp
型。
df.set_index('date', inplace=True)
print(df)
# val_1 val_2
# date
# 2017-11-01 65 76
# 2017-11-07 26 66
# 2017-11-18 47 47
# 2017-11-27 20 38
# 2017-12-05 65 85
# 2017-12-12 4 29
# 2017-12-22 31 54
# 2017-12-29 21 8
# 2018-01-03 98 76
# 2018-01-08 48 64
# 2018-01-19 18 48
# 2018-01-23 86 70
print(type(df.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
print(df.index[0])
print(type(df.index[0]))
# 2017-11-01 00:00:00
# <class 'pandas._libs.tslib.Timestamp'>
年や月で行を指定したり、スライスで期間を抽出したりできる。
print(df['2018'])
# val_1 val_2
# date
# 2018-01-03 98 76
# 2018-01-08 48 64
# 2018-01-19 18 48
# 2018-01-23 86 70
print(df['2017-11'])
# val_1 val_2
# date
# 2017-11-01 65 76
# 2017-11-07 26 66
# 2017-11-18 47 47
# 2017-11-27 20 38
print(df['2017-12-15':'2018-01-15'])
# val_1 val_2
# date
# 2017-12-22 31 54
# 2017-12-29 21 8
# 2018-01-03 98 76
# 2018-01-08 48 64
また、様々な書式で行を指定することもできる。
print(df.loc['01/19/2018', 'val_1'])
# 18
print(df.loc['20180103', 'val_2'])
# 76
非標準の書式の場合
上の例では、日付が標準的な書式だったのでto_datetime
メソッドでそのままdatetime64[ns]
型に変換できたが、非標準の書式の場合、引数format
で書式を指定する必要がある。
%Y
が西暦4桁、%m
がゼロ埋めした2桁の月など、書式化コードは以下のドキュメントを参照。
日付が日本語表記されている場合の例を示す。
df_jp = pd.read_csv('data/src/sample_date_jp.csv')
print(df_jp)
# date val_1 val_2
# 0 2017年11月1日 65 76
# 1 2017年11月7日 26 66
# 2 2017年11月18日 47 47
# 3 2017年11月27日 20 38
# 4 2017年12月5日 65 85
# 5 2017年12月12日 4 29
# 6 2017年12月22日 31 54
# 7 2017年12月29日 21 8
# 8 2018年1月3日 98 76
# 9 2018年1月8日 48 64
# 10 2018年1月19日 18 48
# 11 2018年1月23日 86 70
df_jp['date'] = pd.to_datetime(df_jp['date'], format='%Y年%m月%d日')
df_jp.set_index('date', inplace=True)
print(df_jp)
# val_1 val_2
# date
# 2017-11-01 65 76
# 2017-11-07 26 66
# 2017-11-18 47 47
# 2017-11-27 20 38
# 2017-12-05 65 85
# 2017-12-12 4 29
# 2017-12-22 31 54
# 2017-12-29 21 8
# 2018-01-03 98 76
# 2018-01-08 48 64
# 2018-01-19 18 48
# 2018-01-23 86 70
print(type(df_jp.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
CSV読み込み時にDatetimeIndexを指定
元データがCSVファイルの場合、read_csv()
での読み込み時にDatetimeIndex
を指定することができる。
引数index_col
にインデックスとして使う日時データの列名(または0始まりの列番号)を指定し、parse_dates
をTrue
と設定すればOK。
df = pd.read_csv('data/src/sample_date.csv', index_col='date', parse_dates=True)
print(df)
# val_1 val_2
# date
# 2017-11-01 65 76
# 2017-11-07 26 66
# 2017-11-18 47 47
# 2017-11-27 20 38
# 2017-12-05 65 85
# 2017-12-12 4 29
# 2017-12-22 31 54
# 2017-12-29 21 8
# 2018-01-03 98 76
# 2018-01-08 48 64
# 2018-01-19 18 48
# 2018-01-23 86 70
print(type(df.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
非標準書式の日付文字列をもつCSVファイルの場合、read_csv()
の引数date_parser
にラムダ式で定義したパーサーを指定する。
parser = lambda date: pd.to_datetime(date, format='%Y年%m月%d日')
df_jp = pd.read_csv('data/src/sample_date_jp.csv', index_col='date', parse_dates=True, date_parser=parser)
print(df_jp)
# val_1 val_2
# date
# 2017-11-01 65 76
# 2017-11-07 26 66
# 2017-11-18 47 47
# 2017-11-27 20 38
# 2017-12-05 65 85
# 2017-12-12 4 29
# 2017-12-22 31 54
# 2017-12-29 21 8
# 2018-01-03 98 76
# 2018-01-08 48 64
# 2018-01-19 18 48
# 2018-01-23 86 70
print(type(df_jp.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
pandas.Seriesの場合
実際にはあまりないパターンかも知れないが、pandas.Series
のインデックスが日付の文字列の場合。
s = pd.read_csv('data/src/sample_date.csv', index_col=0, usecols=[0, 1], squeeze=True)
print(s)
# date
# 2017-11-01 65
# 2017-11-07 26
# 2017-11-18 47
# 2017-11-27 20
# 2017-12-05 65
# 2017-12-12 4
# 2017-12-22 31
# 2017-12-29 21
# 2018-01-03 98
# 2018-01-08 48
# 2018-01-19 18
# 2018-01-23 86
# Name: val_1, dtype: int64
print(type(s))
print(type(s.index))
# <class 'pandas.core.series.Series'>
# <class 'pandas.core.indexes.base.Index'>
このインデックスをDatetimeIndex
に変換したい場合は、属性index
にto_datetime
で変換したindex
を代入して上書きしてしまえばOK。
s.index = pd.to_datetime(s.index)
print(s)
# date
# 2017-11-01 65
# 2017-11-07 26
# 2017-11-18 47
# 2017-11-27 20
# 2017-12-05 65
# 2017-12-12 4
# 2017-12-22 31
# 2017-12-29 21
# 2018-01-03 98
# 2018-01-08 48
# 2018-01-19 18
# 2018-01-23 86
# Name: val_1, dtype: int64
print(type(s))
print(type(s.index))
# <class 'pandas.core.series.Series'>
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
print(s['2017-12-15':'2018-01-15'])
# date
# 2017-12-22 31
# 2017-12-29 21
# 2018-01-03 98
# 2018-01-08 48
# Name: val_1, dtype: int64