【问题标题】:Speed up Python .loc function search加快 Python .loc 函数搜索
【发布时间】:2019-06-02 13:34:10
【问题描述】:

我正在从表中提取一个值,并根据其他列中的匹配项搜索该值。现在,因为有数十万个网格单元要经过,所以每次调用该函数需要几秒钟,但加起来需要几个小时。有没有更快的方法来做到这一点?

data_1 = data.loc[(data['test1'] == test1) & (data['test2'] == X) & (data['Column'] == col1) & (data['Row']== row1)].Value

示例data

Column  Row Value   test2   test1
2       3   5       X       0TO4
2       6   10      Y       100UP
2       10  5.64    Y       10TO14
5       2   9.4     Y       15TO19
9       2   6       X       20TO24
13      11  7.54    X       25TO29
25      2   6.222   X       30TO34

【问题讨论】:

  • 预期输出是什么?
  • 看起来像是将值选择为所有列都满足某些条件的列表/系列。
  • 是的。它在匹配所有其他列的同时查找列 Value 中的值

标签: python pandas performance dataframe search


【解决方案1】:

您可以按test1test2ColumnRow 进行索引,然后按该索引进行查找。

索引:

data.set_index(["test1", "test2", "Column", "Row"], inplace=True)

然后通过这样做查找:

data_1 = data.loc[(test1, X, col1, row1)].Value

【讨论】:

  • 对这个答案非常好奇。知道它会加快多少速度吗?
  • 刚刚尝试过,实际上最终花费了更长的时间。在查看 9 行的测试文件上(查询更大的 data 文件,但要查找 9 个值),耗时 1 分 5 秒,而 42 秒
【解决方案2】:

可能值得在enhancing performance docs 上快速通读一下,看看什么最适合您的需求。

一种选择是使用.values 和切片下拉到numpy。在没有看到您的实际数据或用例的情况下,我创建了以下合成数据:

data=pd.DataFrame({'column':[np.random.randint(30) for i in range(100000)],
                'row':[np.random.randint(50) for i in range(100000)],
                'value':[np.random.randint(100)+np.random.rand() for i in range(100000)],
                 'test1':[np.random.choice(['X','Y']) for i in range(100000)],
                'test2':[np.random.choice(['d','e','f','g','h','i']) for i in range(100000)]})

data.head()

    column  row value       test1   test2
0   4       30  88.367151   X       e
1   7       10  92.482926   Y       d
2   1       17  11.151060   Y       i
3   27      10  78.707897   Y       g
4   19      35  95.204207   Y       h

然后使用%timeit 我使用.loc 索引、布尔掩码和numpy 切片得到以下结果 (注意,此时我意识到我错过了其中一个查找,因此可能会影响总时间计数,但比率应该成立)

%timeit data_1 = data.loc[(data['test1'] == 'X') & (data['column'] >=12) & (data['row'] > 22)]['value']
13 ms ± 538 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit data_1 = data[(data['test1'] == 'X') & (data['column'] >=12) & (data['row'] > 22)]['value']
13.1 ms ± 233 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

现在,下一部分包含将数据帧转换为 numpy 数组的一些开销。如果您将其转换一次然后对其进行多次查找,那么这会更快。但如果没有,您最终可能会花费更长的时间来进行单个转换/切片

不考虑转化时间:

d1=data.values

%timeit d1[(d1[:,3]=='X')&(d1[:,0]>=12)&(d1[:,1]>22)][:,2]
8.37 ms ± 161 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

大约 30% 的改进

有转化时间:

%timeit d1=data.values;d1[(d1[:,3]=='X')&(d1[:,0]>=12)&(d1[:,1]>22)][:,2]
20.6 ms ± 624 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

大约差 50%

【讨论】:

  • 我试过这个,转换一次然后索引,数组的测试样本从 42 秒到 33 秒
  • 很高兴这有帮助。我仍然会查看我包含的链接或@scottboston 评论的答案,看看 numba、numexpr/eval 或 cython 是否可能不是一个更大的改进,诚然在前端需要更多的努力
猜你喜欢
  • 2019-01-20
  • 1970-01-01
  • 2021-09-27
  • 2012-03-17
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 2013-04-13
  • 2023-01-05
相关资源
最近更新 更多