いくつかの日付時刻(文字列として)と 'nan'としてnullを含むシリーズがあります。
import pandas as pd, numpy as np, datetime as dt
df = pd.DataFrame({'Date':['2014-10-20 10:44:31', '2014-10-23 09:33:46', 'nan', '2014-10-01 09:38:45']})
これらを日時に変換しようとしています:
df['Date'] = df['Date'].apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
しかし、私はエラーが出ます:
time data 'nan' does not match format '%Y-%m-%d %H:%M:%S'
だから私はこれらを実際のヌルに変えようとします:
df.ix[df['Date'] == 'nan', 'Date'] = np.NaN
そして繰り返す:
df['Date'] = df['Date'].apply(lambda x: dt.datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
しかし、私はエラーを受け取ります:
浮動小数点数ではなく文字列でなければなりません
この問題を解決する最も速い方法は何ですか?
to_datetime
を使用し、errors='coerce'
を設定して、ダフデータを処理します。
In [321]:
df['Date'] = pd.to_datetime(df['Date'], errors='coerce')
df
Out[321]:
Date
0 2014-10-20 10:44:31
1 2014-10-23 09:33:46
2 NaT
3 2014-10-01 09:38:45
In [322]:
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 4 entries, 0 to 3
Data columns (total 1 columns):
Date 3 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 64.0 bytes
strptime
の呼び出しの問題は、文字列またはdtypeが正しくない場合にエラーが発生することです。
あなたがこれをした場合、それはうまくいくでしょう:
In [324]:
def func(x):
try:
return dt.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
except:
return pd.NaT
df['Date'].apply(func)
Out[324]:
0 2014-10-20 10:44:31
1 2014-10-23 09:33:46
2 NaT
3 2014-10-01 09:38:45
Name: Date, dtype: datetime64[ns]
ただし、本質的にシリーズをループするapply
を呼び出すよりも、組み込みのto_datetime
を使用する方が高速です。
タイミング
In [326]:
%timeit pd.to_datetime(df['Date'], errors='coerce')
%timeit df['Date'].apply(func)
10000 loops, best of 3: 65.8 µs per loop
10000 loops, best of 3: 186 µs per loop
to_datetime
を使用すると、3倍高速になることがわかります。
pandasを実行すると、大きなデータフレームでは処理が遅くなりすぎます。別の投稿で、一意の値の数が行(私のデータは通常、株価またはトレードブロッターのデータです)。最初にテキストの日付をそれらのdatetimeオブジェクトにマップするdictを作成し、次にdictを適用してテキストの日付の列を変換します。
def str2time(val):
try:
return dt.datetime.strptime(val, '%H:%M:%S.%f')
except:
return pd.NaT
def TextTime2Time(s):
times = {t : str2time(t) for t in s.unique()}
return s.apply(lambda v: times[v])
df.date = TextTime2Time(df.date)