将 int64 系列转换为日期时间的最有效方法?

bad*_*eas 0 python optimization pandas

设置场景:我有一个 dtype int64 的 Series 对象。我需要将这些转换为仅包含日期的 datetime 对象(没有小时和秒)

到目前为止我有什么工作...

foo.head() =

0    1382400000
1    1382400000
2    1382054400
3    1381708800
4    1380758400
Name: da_0, dtype: int64
Run Code Online (Sandbox Code Playgroud)

这个功能:

def convert_stamp_to_date(stamp):
    try:
        d = datetime.datetime.utcfromtimestamp(stamp)
    except:
        d = datetime.datetime.utcfromtimestamp(0)
    d = datetime.datetime(d.year, d.month, d.day)
    return d
Run Code Online (Sandbox Code Playgroud)

当我处理有问题的系列时,我会打电话给:

foo = foo.apply(lambda x: convert_stamp_to_date(x))
Run Code Online (Sandbox Code Playgroud)

这给了我正确的解决方案:

0   2013-10-22 00:00:00
1   2013-10-22 00:00:00
2   2013-10-18 00:00:00
3   2013-10-14 00:00:00
4   2013-10-03 00:00:00
Name: da_0, dtype: datetime64[ns]
Run Code Online (Sandbox Code Playgroud)

这给了我想要的东西,但是我发现它很慢(应该是这样,对吧?因为它只是做这项工作的天真方式)。

对于长度约 5000 的小型系列对象,平均需要约 27 毫秒进行转换。不......不过,我可以轻松拥有它增长到数百万行的Series对象。对于那些,我看到转换时间进入 1-2 分钟范围。与我使用相同大小的 Series 和 DataFrame 所做的其他事情相比,这似乎太慢了。

我的第一个想法是尝试使用np.vectorize. 然而,这实际上使转换了大约 10 倍。

vconvert_stamp_to_date = np.vectorize(convert_stamp_to_date)
foo = foo.apply(lambda x: vconvert_stamp_to_date(x))
Run Code Online (Sandbox Code Playgroud)

虽然这仍然给了我正确的答案,但它将较小系列对象的转换时间增加到大约 350 毫秒,对于我使用的较大系列,我不得不 ctrl+c 退出脚本,因为它花费了太长时间.

将时间戳转换为日期时间对象将是我程序的瓶颈对我来说似乎有点荒谬:(我必须相信有一种更有效的方法可以在某处执行此操作。任何人都可以指出我正确的方向吗?目前,我已经耗尽了我所有的熊猫法力。如果你能读到这里,我非常感激。

谢谢你。

Jef*_*eff 5

这些看起来像纪元秒,所以只需使用 pd.to_datetime

In [12]: arr = [1382400000] * 1000000

In [14]: pd.to_datetime(arr,unit='s')
Out[14]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-10-22 00:00:00, ..., 2013-10-22 00:00:00]
Length: 1000000, Freq: None, Timezone: None

In [15]: %timeit pd.to_datetime(arr,unit='s')
10 loops, best of 3: 122 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • 你没有秒,也许你有毫秒(尝试将 ``unit='s'`` 更改为 ``unit='ms'`` (2认同)