時系列データを読み込み,DatetimeIndexを持つpandas.DataFrameを作る

Table of Content

日付と時刻の扱い

In [1]:
import pandas as pd
import datetime
from dateutil.parser import parse

日付と時刻を扱うには主に[cci lang="python"]datetime.datetime[/cci]型([cci lang="python"]datetime[/cci]型と略します)を使います.日付や時刻と認識できる様々な文字列を解釈し[cci lang="python"]datetime[/cci]型に変換するのが[cci lang="python"]dateutil[/cci]パッケージの[cci lang="python"]parser.parse[/cci]メソッドです.

In [2]:
### 日時をdatetime型に
datetime1 = parse("2017:12:23 00:00:00")
datetime1
Out[2]:
datetime.datetime(2017, 12, 24, 0, 0)

[cci lang="python"]datetime[/cci]型から年(文字列)を取り出すには[cci lang="python"]datetime.strftime("%Y")[/cci]とします.よく使うものをまとめると,[cci lang="python"]"%Y"[/cci]: 4桁の年,[cci lang="python"]"%m"[/cci]: 2桁の月[01,12],[cci lang="python"]"%d"[/cci]: 2桁の日[01,31],[cci lang="python"]"%H"[/cci]: 2桁の時間[00,23],[cci lang="python"]"%M"[/cci]: 2桁の分[00, 59],[cci lang="python"]"%S"[/cci]: 2桁の秒[00, 61](60と61はうるう秒を考慮),[cci lang="python"]"%z"[/cci]: UTC時間からのずれを[cci lang="python"]+HHMM[/cci]または[cci lang="python"]-HHMM[/cci]形式で表したもの,[cci lang="python"]"%F"[/cci]: [cci lang="python"]"%Y-%m-%d"[/cci]を短縮したもの(例:[cci lang="python"]"2017-1-27"[/cci]),となります.

In [3]:
datetime1.strftime("%Y")
Out[3]:
'2017'

[cci lang="python"]pandas[/cci]の[cci lang="python"]to_datetime[/cci]メソッドで日付時刻の文字列からなるリストを[cci lang="python"]pandas[/cci]の[cci lang="python"]DatetimeIndex[/cci]に変換でき,その1要素(あるいはスカラー)は[cci lang="python"]Timestamp[/cci]オブジェクトになります.つまり,[cci lang="python"]Timestamp[/cci]オブジェクトで構成されたリストが[cci lang="python"]datetimeIndex[/cci]です.[cci lang="python"]to_datetime[/cci]メソッドには[cci lang="python"]datetime[/cci]型を渡すこともできます.一方,[cci lang="python"]datetime.strftime[/cci]は[cci lang="python"]DatetimeIndex[/cci]や[cci lang="python"]Timestamp[/cci]には使えません.

In [4]:
pd.to_datetime(["2017-1-2", "2017-9-30"])
Out[4]:
DatetimeIndex(['2017-01-02', '2017-09-30'], dtype='datetime64[ns]', freq=None)
In [5]:
pd.to_datetime(["2017-1-2", "2017-9-30"])[0]  ### 1つめの要素を抽出
Out[5]:
Timestamp('2017-01-02 00:00:00')
In [6]:
pd.to_datetime(datetime1)
Out[6]:
Timestamp('2017-12-24 00:00:00')

日付時刻をカラムに含むデータをDataFrameとして読み込み,indexをDatetimeIndexにする

以下のようなdataを用意します.

In [7]:
data={"YYYY": [1991, 1992], "MM": [2, 10], "DD": [16, 29], "HH": [2, 14], "data": [0.2, 1.7]}
pd.DataFrame(data)
Out[7]:
DD HH MM YYYY data
0 16 2 2 1991 0.2
1 29 14 10 1992 1.7

辞書で作ったのでカラムの順番がdataと異なっています.カラムの順番を入れ替えます.

In [8]:
df=pd.DataFrame(data).loc[:,["YYYY", "MM", "DD", "HH", "data"]]
df
Out[8]:
YYYY MM DD HH data
0 1991 2 16 2 0.2
1 1992 10 29 14 1.7

これをCSVファイルとして出力します.indexは削除します.

In [9]:
df.to_csv("data.csv", index=None)

このdata.csvを読み込みDataFrame化します.

In [10]:
pd.read_csv("data.csv")
Out[10]:
YYYY MM DD HH data
0 1991 2 16 2 0.2
1 1992 10 29 14 1.7

年月日をインデックスにして[cci lang="python"]data.csv[/cci]を読み込みます.[cci lang="python"]parse_dates[/cci]では[cci lang="python"][[0,1,2]][/cci]と二重のカギ括弧とすることでカラム0,1,2を一つに繋げ[cci lang="python"]parse[/cci]します.

In [11]:
pd.read_csv("data.csv", index_col=[0,1,2], parse_dates=[[0,1,2]])
Out[11]:
YYYY_MM_DD HH data
1991-02-16 2 0.2
1992-10-29 14 1.7

[cci lang="python"]parse_dates[/cci]にカラム名を含む辞書を渡し,そのカラム名を[cci lang="python"]index_col[/cci]に指定することもできます.

In [12]:
pd.read_csv("data.csv", index_col="date", parse_dates={"date":[0,1,2]})
Out[12]:
HH data
date
1991-02-16 2 0.2
1992-10-29 14 1.7

dateとtimeを同時に読み込み,date_parser=my_parserで一気にDatetimeIndexを作る

しかし,時刻HHはこの方法では処理できません.[cci lang="python"]date_parser[/cci]に自前のラムダ関数[cci lang="python"]my_parser[/cci]を用意するのが一つの方法です.ただし,[cci lang="python"]index_col=[0,1,2,3][/cci]とすると[cci lang="python"]list index out of range[/cci]のエラーになります.おそらく,dateしか想定していないため,カラム数が3つまででないとだめなのではないかと推察します.[cci lang="python"]index_col="datetime"[/cci]のように[cci lang="python"]parse_dates[/cci]の辞書で指定したインデックス名を使えばうまくいきます.
ラムダ関数の引数は[cci lang="python"][0,1,2,3][/cci]を統合したものではなく,それぞれの要素です.これをy, m, d, hとすると,[cci lang="python"]fmt[/cci]と[cci lang="python"]strptime[/cci]の第一引数が整合するように両者を定義します.この方法はおそらくどのような形式でも対応できるのではないかと思います.

In [13]:
fmt = '%Y-%m-%d %H'
my_parser = lambda y, m, d, h: pd.datetime.strptime(y + "-" + m + "-" + d + " " + h, fmt)
pd.read_csv("data.csv", index_col="datetime", parse_dates={"datetime": [0,1,2,3]}, date_parser=my_parser)
Out[13]:
data
datetime
1991-02-16 02:00:00 0.2
1992-10-29 14:00:00 1.7

DataFrameのカラムを結合してDatetimeIndexを作る

別の方法として,原始的ですが,簡単に解釈できる日付と時刻を分け,それぞれをカラムとして読み込み,後で結合してインデックス化することもできます.まず,[cci lang="python"]DataFrame df[/cci]を作ります.

In [14]:
df = pd.read_csv("data.csv", parse_dates=[[0,1,2]])
df
Out[14]:
YYYY_MM_DD HH data
0 1991-02-16 2 0.2
1 1992-10-29 14 1.7

2つのカラムYYYY_MM_DD([cci lang="python"]DateTimeIndex[/cci])とHH(整数のリスト)を取り出し,リスト内包でそれぞれをx([cci lang="python"]Timestamp[/cci]), y (整数)として取り出し,[cci lang="python"]Hour(y)[/cci]で日付オフセットに変換し,両者を足し合わせた[cci lang="python"]Timestamp[/cci]を作ります.
よく使う日付オフセットは,[cci lang="python"]Hour()[/cci], [cci lang="python"]Minute()[/cci], [cci lang="python"]Second()[/cci], [cci lang="python"]Day()[/cci],です.[cci lang="python"]Hour()[/cci]は1時間,[cci lang="python"]Hour(3)[/cci]は3時間です.

In [15]:
from pandas.tseries.offsets import Hour ### 時間の単位である,Hourが必要です
df.index=[x + Hour(y) for x,y in zip(df['YYYY_MM_DD'],df['HH'])]
df.index.name="datetime"  ### index名を設定
df
Out[15]:
YYYY_MM_DD HH data
datetime
1991-02-16 02:00:00 1991-02-16 2 0.2
1992-10-29 14:00:00 1992-10-29 14 1.7

カラムを削除する

不要となった列の削除は[cci lang="python"]DataFrame[/cci]の[cci lang="python"]drop[/cci]メソッドを適用します.カラムが対象なので,[cci lang="python"]axis=1[/cci]が必要です.

In [16]:
df.drop(["YYYY_MM_DD", "HH"], axis=1)
Out[16]:
data
datetime
1991-02-16 02:00:00 0.2
1992-10-29 14:00:00 1.7

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください