web-dev-qa-db-ja.com

文字列をnullのあるdatetimeに変換する方法-Python、パンダ?

いくつかの日付時刻(文字列として)と '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'))

しかし、私はエラーを受け取ります:

浮動小数点数ではなく文字列でなければなりません

この問題を解決する最も速い方法は何ですか?

15
Colin O'Brien

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倍高速になることがわかります。

29
EdChum

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)
3
jdmarino