有効な日付を持つ標準の YYYY-MM-DD 文字列によってインデックスが作成されているにもかかわらず、DatetimeIndex として認識されない時系列があります。それらを有効な DatetimeIndex に強制することは、私が何か間違ったことをしていると思わせるほどエレガントではないようです。
無効な日時値を含む (他の誰かの遅延フォーマットされた) データを読み込み、これらの無効な観測を削除します。
In [1]: df = pd.read_csv('data.csv',index_col=0)
In [2]: print df['2008-02-27':'2008-03-02']
Out[2]:
count
2008-02-27 20
2008-02-28 0
2008-02-29 27
2008-02-30 0
2008-02-31 0
2008-03-01 0
2008-03-02 17
In [3]: def clean_timestamps(df):
# remove invalid dates like '2008-02-30' and '2009-04-31'
to_drop = list()
for d in df.index:
try:
datetime.date(int(d[0:4]),int(d[5:7]),int(d[8:10]))
except ValueError:
to_drop.append(d)
df2 = df.drop(to_drop,axis=0)
return df2
In [4]: df2 = clean_timestamps(df)
In [5] :print df2['2008-02-27':'2008-03-02']
Out[5]:
count
2008-02-27 20
2008-02-28 0
2008-02-29 27
2008-03-01 0
2008-03-02 17
この新しいインデックスは、DatetimeIndex ではなく「オブジェクト」dtype としてのみ認識されます。
In [6]: df2.index
Out[6]: Index([2008-01-01, 2008-01-02, 2008-01-03, ..., 2012-11-27, 2012-11-28,
2012-11-29], dtype=object)
NaN は異なる dtype であるため、インデックスを再作成すると NaN が生成されます。
In [7]: i = pd.date_range(start=min(df2.index),end=max(df2.index))
In [8]: df3 = df2.reindex(index=i,columns=['count'])
In [9]: df3['2008-02-27':'2008-03-02']
Out[9]:
count
2008-02-27 NaN
2008-02-28 NaN
2008-02-29 NaN
2008-03-01 NaN
2008-03-02 NaN
適切なインデックスを使用して新しいデータフレームを作成し、データをディクショナリにドロップしてから、ディクショナリの値に基づいて新しいデータフレームに入力します (欠損値をスキップします)。
In [10]: df3 = pd.DataFrame(columns=['count'],index=i)
In [11]: values = dict(df2['count'])
In [12]: for d in i:
try:
df3.set_value(index=d,col='count',value=values[d.isoformat()[0:10]])
except KeyError:
pass
In [13]: print df3['2008-02-27':'2008-03-02']
Out[13]:
count
2008-02-27 20
2008-02-28 0
2008-02-29 27
2008-03-01 0
2008-03-02 17
In [14]: df3.index
Out[14];
<class 'pandas.tseries.index.DatetimeIndex'>
[2008-01-01 00:00:00, ..., 2012-11-29 00:00:00]
Length: 1795, Freq: D, Timezone: None
文字列をキーとするディクショナリへのルックアップに基づいて値を設定するこの最後の部分は、特にハッキリしているようで、何か重要なことを見逃しているように思えます。