使用pd.to_datetime处理多个日期时间格式

时间:2017-11-13 02:17:20

标签: python pandas date datetime

我有数据时间数据,其格式类似于2906201701AUG2017。 如您所见,月份处于数据中间。

当我使用pd.to_datetime时,我想将此数据转换为日期时间,但它不起作用。

你知道解决这个问题的好方法吗?

4 个答案:

答案 0 :(得分:5)

替代方法是使用映射器和replace替换月份代码及其等效数字:

s = pd.Series(["29062017", "01AUG2017"]); s

0     29062017
1    01AUG2017
dtype: object

m = {'JAN' : '01', ..., 'AUG' : '08', ...}  # you fill in the rest

s = s.replace(m, regex=True); s

0    29062017
1    01082017
dtype: object

现在您只需要一个pd.to_datetime电话:

pd.to_datetime(s, format="%d%m%Y", errors="coerce")

0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

答案 1 :(得分:4)

我想谈谈一些选择

设置

m = dict(
    JAN='01', FEB='02', MAR='03', APR='04',
    MAY='05', JUN='06', JUL='07', AUG='08',
    SEP='09', OCT='10', NOV='11', DEC='12'
)

m2 = m.copy()
m2.update({v: v for v in m.values()})

f = lambda x: m.get(x, x)

选项1
列表理解

pd.Series(
    pd.to_datetime(
        [x[:2] + f(x[2:5]) + x[5:] for x in s.values.tolist()],
        format='%d%m%Y'),
    s.index)

0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

选项2
创建数据框

pd.to_datetime(
    pd.DataFrame(dict(
        day=s.str[:2],
        year=s.str[-4:],
        month=s.str[2:-4].map(m2)
    )))

0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

选项2B
创建数据框

pd.to_datetime(
    pd.DataFrame(dict(
        day=s.str[:2],
        year=s.str[-4:],
        month=s.str[2:-4].map(f)
    )))

0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

选项2C
创建数据框
我估计这是最快的

pd.to_datetime(
    pd.DataFrame(dict(
        day=s.str[:2].astype(int),
        year=s.str[-4:].astype(int),
        month=s.str[2:-4].map(m2).astype(int)
    )))

0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

测试

s = pd.Series(["29062017", "01AUG2017"] * 100000)

%timeit pd.to_datetime(s.replace(m, regex=True), format='%d%m%Y')
%timeit pd.to_datetime(s.str[:2] + s.str[2:5].replace(m) + s.str[5:], format='%d%m%Y')
%timeit pd.to_datetime(s.str[:2] + s.str[2:5].map(f) + s.str[5:], format='%d%m%Y')
%timeit pd.to_datetime(s, format='%d%m%Y', errors='coerce').fillna(pd.to_datetime(s, format='%d%b%Y', errors='coerce'))
%timeit pd.Series(pd.to_datetime([x[:2] + f(x[2:5]) + x[5:] for x in s.values.tolist()], format='%d%m%Y'), s.index)
%timeit pd.to_datetime(pd.DataFrame(dict(day=s.str[:2], year=s.str[-4:], month=s.str[2:-4].map(m2))))
%timeit pd.to_datetime(pd.DataFrame(dict(day=s.str[:2], year=s.str[-4:], month=s.str[2:-4].map(f))))
%timeit pd.to_datetime(pd.DataFrame(dict(day=s.str[:2].astype(int), year=s.str[-4:].astype(int), month=s.str[2:-4].map(m2).astype(int))))

1.39 s ± 24 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
690 ms ± 17.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
613 ms ± 13.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
533 ms ± 14.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
529 ms ± 8.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
557 ms ± 13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
607 ms ± 26.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
328 ms ± 31.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 2 :(得分:3)

由于您有两种类型的日期时间......

record = tf.reshape(tf.decode_raw(data, tf.uint8), [record_bytes])

答案 3 :(得分:2)

您可以使用pd.to_datetime的格式arg:

In [11]: s = pd.Series(["29062017", "01AUG2017"])

In [12]: pd.to_datetime(s, format="%d%m%Y", errors="coerce")
Out[12]:
0   2017-06-29
1          NaT
dtype: datetime64[ns]

In [13]: pd.to_datetime(s, format="%d%b%Y", errors="coerce")
Out[13]:
0          NaT
1   2017-08-01
dtype: datetime64[ns]

注意:coerce参数表示失败为NaT

并将NaN从一个填写到另一个,例如使用fillna

In [14]: pd.to_datetime(s, format="%d%m%Y", errors="coerce").fillna(pd.to_datetime(s, format="%d%b%Y", errors="coerce"))
Out[14]:
0   2017-06-29
1   2017-08-01
dtype: datetime64[ns]

任何格式都不匹配的字符串将保留NaT。