note.nkmk.me

pandas.DataFrame, Seriesを時系列データとして処理

Date: 2018-02-01 / tags: Python, pandas
このエントリーをはてなブックマークに追加

pandas.DataFrame, pandas.Seriesのインデックスをdatetime64型にするとDatetimeIndexとみなされ、時系列データを処理する様々な機能が使えるようになる。

年や月で行を指定したりスライスで期間を抽出したりできるので、日付や時刻など日時の情報が入ったデータを処理する場合は便利。

例えば、曜日や年、月ごとの合計や平均を算出するのも簡単にできるようになる。

ここでは、

  • 既存データの列をDatetimeIndexとして指定する方法
  • csv読み込み時にDatetimeIndexを指定する方法

について説明する。

例として、以下のcsvデータを使う。

既存データの列をDatetimeIndexとして指定

デフォルトの単調増加のインデックスと日付の文字列の列を持つ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型に変換する。

df['date'] = pd.to_datetime(df['date'])
print(df['date'].dtype)
# datetime64[ns]

set_index()メソッドでdatetime64型の列をインデックスに指定する。

これでインデックスが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型に変換できたが、非標準の書式の場合、引数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_datesTrueと設定すれば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に変換したい場合は、属性indexto_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
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事