熊猫时间戳与日期时间的性能缓慢

Posted

技术标签:

【中文标题】熊猫时间戳与日期时间的性能缓慢【英文标题】:Slow performance of pandas timestamp vs datetime 【发布时间】:2015-05-25 01:36:37 【问题描述】:

我似乎在 pandas.Timestamp 与 python 常规 datetime() 对象上的算术运算性能出乎意料地慢。 下面是一个演示基准:

import datetime
import pandas
import numpy

# using datetime:
def test1():
    d1 = datetime.datetime(2015, 3, 20, 10, 0, 0)
    d2 = datetime.datetime(2015, 3, 20, 10, 0, 15)
    delta = datetime.timedelta(minutes=30)

    count = 0
    for i in range(500000):
        if d2 - d1 > delta:
            count += 1

# using pandas:
def test2():
    d1 = pandas.datetime(2015, 3, 20, 10, 0, 0)
    d2 = pandas.datetime(2015, 3, 20, 10, 0, 15)
    delta = pandas.Timedelta(minutes=30)

    count = 0
    for i in range(500000):
        if d2 - d1 > delta:
            count += 1

# using numpy
def test3():
    d1 = numpy.datetime64('2015-03-20 10:00:00')
    d2 = numpy.datetime64('2015-03-20 10:00:15')
    delta = numpy.timedelta64(30, 'm')

    count = 0
    for i in range(500000):
        if d2 - d1 > delta:
            count += 1


  time1 = datetime.datetime.now()
  test1()
  time2 = datetime.datetime.now()
  test2()
  time3 = datetime.datetime.now()
  test3()
  time4 = datetime.datetime.now()

  print('DELTA test1: ' + str(time2-time1))
  print('DELTA test2: ' + str(time3-time2))
  print('DELTA test3: ' + str(time4-time3))

以及我机器上对应的结果(python3.3,pandas 0.15.2):

DELTA test1: 0:00:00.131698
DELTA test2: 0:00:10.034970
DELTA test3: 0:00:05.233389

这是预期的吗? 除了尽可能将代码切换到 Python 的默认日期时间实现之外,还有其他方法可以消除性能问题吗?

【问题讨论】:

集中我的问题:我知道 pandas 和 numpy 用于矢量化处理。 问题出在应用程序中执行矢量处理的部分和处理离散值/事件的部分之间的接口:如果提供 pandas 日期时间表示,离散处理代码会受到影响。跨度> 好的,在这种情况下,如果您的基准测试代表您的用例,那么绝对没有理由使用 numpy 或 pandas 日期时间。下面我构建了一个替代示例,展示了 pandas datetime 会更快的情况。当然,我不能确定它在多大程度上代表了您的用例。 另外,您可能会考虑发布实际代码的简化版本,并询问是否有人有加快速度的想法。人们通常更容易对这类问题给出具体而实用的答案。 【参考方案1】:

我的机器上也有类似的结果:

$ python -mtimeit -s "from datetime import datetime, timedelta; d1, d2 = datetime(2015, 3, 20, 10, 0, 0), datetime(2015, 3, 20, 10, 0, 15); delta = timedelta(minutes=30)" "(d2 - d1) > delta"
10000000 loops, best of 3: 0.107 usec per loop
$ python -mtimeit -s "from numpy import datetime64, timedelta64; d1, d2 = datetime64('2015-03-20T10:00:00Z'), datetime64('2015-03-20T10:00:15Z'); delta = timedelta64(30, 'm')" "(d2 - d1) > delta"
100000 loops, best of 3: 5.35 usec per loop
$ python -mtimeit -s "from pandas import Timestamp, Timedelta; d1, d2 = Timestamp('2015-03-20T10:00:00Z'), Timestamp('2015-03-20T10:00:15Z'); delta = Timedelta(minutes=30)" "(d2 - d1) > delta"
10000 loops, best of 3: 19.9 usec per loop

datetime 比对应的 numpypandas 类似物快几倍。

$ python -c "import numpy, pandas; print(numpy.__version__, pandas.__version__)"
('1.9.2', '0.15.2')

目前尚不清楚为什么差异如此之大。确实,numpypandas 代码针对矢量化操作进行了优化。但不清楚为什么这些特定的标量操作要慢两个数量级,例如,显式时区的添加不会减慢datetime.datetime 代码:

$ python3 -mtimeit -s "from datetime import datetime, timedelta, timezone; d1, d2 = datetime(2015, 3, 20, 10, 0, 0, tzinfo=timezone.utc), datetime(2015, 3, 20, 10, 0, 15, tzinfo=timezone.utc); delta = timedelta(minutes=30)" "(d2 - d1) > delta"
10000000 loops, best of 3: 0.0939 usec per loop

要解决此问题,如果您不能使用矢量化操作,您可以尝试将原生日期/时间类型整体转换为更简单(更快)的类似物(例如,POSIX 时间戳表示为浮点数)。

【讨论】:

感谢 J.F 和 John 的回答。底线:pandas 用于批处理,python 用于离散。

以上是关于熊猫时间戳与日期时间的性能缓慢的主要内容,如果未能解决你的问题,请参考以下文章

时间戳与日期的转化————小程序

时间戳与日期相互转换

Python时间戳与日期的相互转化

javascript时间戳与日期格式的相互转换

js时间戳与日期格式之间的互转

将时间戳与查询中的日期名称相等,并在 PostgreSQL 查询中获取结果集 w.r.t 日期名称