日付と時刻の扱い

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

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

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

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

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

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

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

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

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

parse_datesにカラム名を含む辞書を渡し,そのカラム名をindex_colに指定することもできます.

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

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を作る

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

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(DateTimeIndex)とHH(整数のリスト)を取り出し,リスト内包でそれぞれをx(Timestamp), y (整数)として取り出し,Hour(y)で日付オフセットに変換し,両者を足し合わせたTimestampを作ります.
よく使う日付オフセットは,Hour(), Minute(), Second(), Day(),です.Hour()は1時間,Hour(3)は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

カラムを削除する

不要となった列の削除はDataFramedropメソッドを適用します.カラムが対象なので,axis=1が必要です.

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