提高熊猫布尔索引的速度

问题描述 投票:0回答:2

将布尔索引与示例数据一起使用可以很好地工作,但是随着我增加数据的大小,计算时间正呈指数增长(以下示例)。有谁知道一种提高特定布尔索引器速度的方法?

import pandas as pd
import numpy as np
a = pd.date_range('2019-01-01', '2019-12-31',freq = '1T')
b = np.random.normal(size = len(a), loc = 50)
c = pd.DataFrame(index = a, data = b, columns = ['price'])

1500行:

z = c.head(1500)
z[z.index.map(lambda x : 8 <= x.hour <= 16 ) & z.index.map(lambda x : x.weekday() < 5 )]

CPU times: user 149 ms, sys: 8.71 ms, total: 158 ms Wall time: 157 ms

5000行:

z = c.head(5000)
z[z.index.map(lambda x : 8 <= x.hour <= 16 ) & z.index.map(lambda x : x.weekday() < 5 )]

CPU times: user 14.1 s, sys: 9.07 s, total: 23.2 s Wall time: 23.2 s

[我尝试使用z = c.head(10000),但计算时间超过15分钟,所以我停止了...我想在该索引器上使用的数据大小约为30000行。

python pandas
2个回答
1
投票

之所以无法快速运行,是因为您使用lambda表达式执行了映射,这意味着将对每个项目进行一个函数调用。如果要“批量”处理数据,通常不是一个好主意。您可以通过以下方法加快速度:

hour = z.index.hour
z[(8 <= hour) & (hour <= 16) & (z.index.weekday < 5)]

[具有z = c(所以总共524'161行),我们得到以下计时:

>>> z = c
>>> timeit(lambda: z[(8 <= z.index.hour) & (z.index.hour <= 16) & (z.index.weekday < 5)], number=100)
11.825318349001464

因此,每次运行总共需要约118毫秒。

当我们使用前5 000行时,我们得到:

>>> z = c.head(5000)
>>> timeit(lambda: z[(8 <= z.index.hour) & (z.index.hour <= 16) & (z.index.weekday < 5)], number=100)
0.1542488380218856

因此,每次运行的时间为1.5毫秒。


1
投票

z.index.map(lambda x : 8 <= x.hour <= 16)z.index.map(lambda x: x.weekday() < 5)都几乎立即执行。当您将它们与按位运算符&结合使用时,会发生问题。

pd.Index.map返回另一个pd.Index对象。实际上,Index对象上的&运算符确实设置了交集;它不是“元素明智的”。如果查看结果,您会发现它不是您期望的结果,而是5000Trues。花费这么长时间的原因是,这些比较返回的布尔值当然是重复的,并且在这种情况下索引交集失败。

当然,正确的处理方法是使用向量化操作,但是如果您需要以某种方式逐个比较两个pd.Index对象,可以通过将它们转换为numpy数组来实现:

res1 = z.index.map(lambda x : 8 <= x.hour <= 16 ).to_numpy()
res2 = z.index.map(lambda x : x.weekday() < 5 ).to_numpy()
z[res1 & res2]
© www.soinside.com 2019 - 2024. All rights reserved.