什么比 np.sum 和 numpy 布尔运算符更有效?

What is more efficient that np.sum and numpy boolean operators?

提问人:Emaad Shamsi 提问时间:7/13/2020 最后编辑:Emaad Shamsi 更新时间:7/13/2020 访问量:91

问:

我在快速运行代码时遇到了一些问题。

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

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)]

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

任何建议都是值得赞赏的。

python 数组 numpy boolean-logic

评论

2赞 hpaulj 7/13/2020
“datetimes”和“date time”含糊不清。显示一些创建此数组的实际代码。此外,我看不出这样的行如何适合“迭代/循环/映射/减少/过滤”上下文。
1赞 Ehsan 7/13/2020
请提供示例输入。
0赞 Emaad Shamsi 7/13/2020
迭代部分不是必需的,所以我删除了它。我添加了示例输入
1赞 Paul H 7/13/2020
您可能(或现在可能)从 numpy datetime64 或 pandas timestamp 对象的数组中榨取更高的效率

答:

1赞 Paul H 7/13/2020 #1

看起来对象非常快。比标准库速度提高约 2 倍。熊猫在这里挣扎。如果您使用 pandas Timestamps 作为 Series 对象的索引并使用访问器,它比您在下面看到的要好一些。但并没有好到哪里去。numpy.datetime64datetime.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 个循环)

评论

0赞 Emaad Shamsi 7/13/2020
嘿,谢谢你的回答。这是否意味着将我的日期时间值从标准日期时间转换为 np.datetime64 然后执行我的操作会更便宜?强制转换是否会在每个循环中增加我应该避免的额外操作?
1赞 Paul H 7/13/2020
@EmaadShamsi我提前完成了所有的选角。正如你在这里看到的,我没有安排选角的时间。包括强制转换在内的总运行时间将根据您拥有的数据量而有所不同,应根据具体情况进行评估
0赞 Emaad Shamsi 7/15/2020
我明白,它仍然非常有用的信息。我刚刚检查了一下,我实际上使用的是熊猫时间戳,而不是日期时间。如何将其转换为 DataFrame 中的 np.datetime64?另外,您是否知道一种比使用 numpy 库更有效的方法来计算两个语句是否都为真?
1赞 Paul H 7/15/2020
你试过@EmaadShamsi?numpy.datetime64(timestamp)