【问题标题】:What is more efficient that np.sum and numpy boolean operators?什么比 np.sum 和 numpy 布尔运算符更有效?
【发布时间】:2020-11-02 05:17:12
【问题描述】:

我无法让我的代码快速运行。

在我的代码上使用逐行分析器后,我发现以下几行是我大部分效率低下的原因:

import numpy as np
import datetime

timestamps = np.array(timestamps)
mask = (minTime <= timestamps) & (timestamps <= maxTime)
count = np.sum(mask)

timestamps 以日期时间列表开头,minTime 是单个日期时间。

时间戳的示例值:

minTime = datetime.datetime(2020, 5, 21, 2, 27, 26)

timestamps = [datetime.datetime(2020, 5, 21, 2, 27, 26), datetime.datetime(2020, 5, 21, 2, 27, 26), 
 datetime.datetime(2020, 5, 21, 2, 27, 26), datetime.datetime(2020, 5, 21, 2, 30, 55),
 datetime.datetime(2020, 5, 21, 2, 30, 55), datetime.datetime(2020, 5, 21, 2, 30, 55),
 datetime.datetime(2020, 5, 21, 2, 34, 26), datetime.datetime(2020, 5, 21, 2, 34, 26),
 datetime.datetime(2020, 5, 21, 2, 34, 26), datetime.datetime(2020, 5, 21, 2, 39, 26),
 datetime.datetime(2020, 5, 21, 2, 39, 26), datetime.datetime(2020, 5, 21, 2, 39, 26)]

有没有更高效的方法来重写上面的代码?

感谢任何建议。

【问题讨论】:

  • 'datetimes' 和 'date time' 含糊不清。显示一些创建此数组的实际代码。我也看不出这样的行如何适合“迭代/循环/映射/减少/过滤”上下文。
  • 请提供示例输入。
  • 迭代部分不是必需的,所以我删除了它。我已经添加了示例输入
  • 您可能(或现在可能)从 numpy datetime64 或 pandas 时间戳对象数组中榨取更多效率

标签: python arrays numpy boolean boolean-logic


【解决方案1】:

看起来numpy.datetime64 对象非常快。比标准库datetime 提速大约 2 倍。熊猫种比目鱼在这里。如果您使用 pandas Timestamps 作为 Series 对象的索引并使用 .loc 访问器,它比您在下面看到的要好一点。但也没有那么好。

from datetime import datetime

import numpy
import pandas


py_dts = numpy.array([
    datetime(2020, 5, 21, 2, 27, 26),
    datetime(2020, 5, 21, 2, 27, 26), 
    datetime(2020, 5, 21, 2, 27, 26),
    datetime(2020, 5, 21, 2, 30, 55),
    datetime(2020, 5, 21, 2, 30, 55),
    datetime(2020, 5, 21, 2, 30, 55),
    datetime(2020, 5, 21, 2, 34, 26),
    datetime(2020, 5, 21, 2, 34, 26),
    datetime(2020, 5, 21, 2, 34, 26),
    datetime(2020, 5, 21, 2, 39, 26),
    datetime(2020, 5, 21, 2, 39, 26),
    datetime(2020, 5, 21, 2, 39, 26)
])

min_pydt = datetime(2020, 5, 21, 2, 27, 26)
max_pydt = datetime(2020, 5, 21, 2, 39, 26)

min_npdt = numpy.datetime64(min_pydt)
max_npdt = numpy.datetime64(max_pydt)

min_pddt = pandas.Timestamp(min_pydt)
max_pddt = pandas.Timestamp(max_pydt)

np_64s = numpy.array([numpy.datetime64(d) for d in py_dts])
pd_tss = pandas.Series([pandas.Timestamp(d) for d in py_dts])


def counter(timestamps, mindt, maxdt):    
    return ((mindt <= timestamps) & (timestamps <= maxdt)).sum()

在我做的 Jupyter 笔记本中:

%%timeit
counter(py_dts, min_pydt, max_pydt)

每个循环 17.4 µs ± 1.31 µs(7 次运行的平均值 ± 标准偏差,每次 100000 个循环)

%%timeit
counter(np_64s, min_npdt, max_npdt)

每个循环 7.42 µs ± 102 ns(平均值 ± 标准偏差,7 次运行,每次 100000 次循环)

%%timeit
counter(pd_tss, min_pddt, max_pddt)

每个循环 531 µs ± 2.99 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)

【讨论】:

  • 您好,谢谢您的回答。这是否意味着将我的日期时间值从标准日期时间转换为 np.datetime64 然后进行操作会更便宜?强制转换是否会在每个循环中添加一个我应该避免的额外操作?
  • @EmaadShamsi 我提前做了所有的选角。正如你在此处看到的,我没有为选角计时。包括转换在内的总运行时间将根据您拥有的数据量而有所不同,应根据具体情况进行评估
  • 我明白了,它仍然非常有用的信息。我刚刚检查了一下,实际上我使用的是熊猫时间戳而不是日期时间。我如何将它转换为我的 DataFrame 中的 np.datetime64 ?另外,您是否知道一种计算两个语句是否为真的方法,这种方法比使用 numpy 库更有效?
  • @EmaadShamsi 你试过numpy.datetime64(timestamp)吗?
猜你喜欢
  • 2017-08-03
  • 2011-09-27
  • 2011-03-27
  • 2015-08-17
  • 2019-04-05
  • 1970-01-01
相关资源
最近更新 更多