【问题标题】:How do I access a numpy array as quickly as a pandas dataframe如何像 pandas 数据框一样快速访问 numpy 数组
【发布时间】:2016-09-17 02:32:48
【问题描述】:

我比较了访问DataFrame 中数据的几种方法。请参阅下面的结果。最快的访问是在DataFrame 上使用get_value 方法。我在post 上被提及。

令我惊讶的是,通过get_value 访问比通过底层numpy 对象df.values 访问更快。

问题

我的问题是,有没有办法像通过 get_value 访问 pandas 数据框一样快地访问 numpy 数组的元素?

设置

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(16).reshape(4, 4))

测试

%%timeit
df.iloc[2, 2]

10000 次循环,3 次中的最佳:每个循环 108 µs

%%timeit
df.values[2, 2]

最慢的运行时间是最快的运行时间的 5.42 倍。这可能意味着正在缓存中间结果。 100000 次循环,3 次中的最佳:每个循环 8.02 µs

%%timeit
df.iat[2, 2]

最慢的运行时间是最快的运行时间的 4.96 倍。这可能意味着正在缓存中间结果。 100000 次循环,最佳 3 次:每个循环 9.85 µs

%%timeit
df.get_value(2, 2)

最慢的运行时间是最快的运行时间的 19.29 倍。这可能意味着正在缓存中间结果。 100000 次循环,最佳 3 次:每个循环 3.57 µs

【问题讨论】:

  • 对于曾经否决过这个问题的人,我希望能得到一些关于原因的反馈。谢谢
  • 如果你的瓶颈是单元素访问,那么你应该一次访问多个元素
  • 另外,您可能想检查x = df.values; %timeit x[2,2] 是否给出了类似的结果——也许values 不是属性而是property

标签: python numpy pandas


【解决方案1】:

iloc 非常通用,接受切片和列表以及简单的整数。在上面的例子中,你有简单的整数索引,pandas 首先确定它是一个有效的整数,然后将请求转换为iat 索引,所以显然它会慢得多。 iat 最终归结为对get_value 的调用,因此自然直接调用get_value 会很快。 get_value 本身已被缓存,因此此类微基准测试可能无法反映实际代码中的性能。

df.values 确实返回了一个 ndarray,但只有在检查它是单个连续块之后。这需要一些查找和测试,因此比从缓存中检索值要慢一些。

我们可以通过每次创建一个新的数据框来消除缓存。这表明values 访问器是最快的,至少对于统一类型的数据:

In [111]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4))
10000 loops, best of 3: 186 µs per loop

In [112]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4)); df.values[2,2]
1000 loops, best of 3: 200 µs per loop

In [113]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4)); df.get_value(2,2)
1000 loops, best of 3: 309 µs per loop

In [114]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4)); df.iat[2,2]
1000 loops, best of 3: 308 µs per loop

In [115]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4)); df.iloc[2,2]
1000 loops, best of 3: 420 µs per loop

In [116]: %timeit df = pd.DataFrame(np.arange(16).reshape(4, 4)); df.ix[2,2]
1000 loops, best of 3: 316 µs per loop

代码声称ix是最通用的,所以理论上应该比iloc慢;可能是您的特定测试偏爱ix,但其他测试可能偏爱iloc,只是因为将索引标识为标量索引所需的测试顺序。

【讨论】:

  • 除了提供一个很好的答案之外,我还要感谢您提供了将缓存与性能检查分离的良好技术。运行 df 创建作为基准,然后进行从头开始创建 df 的测试,非常适合确定使用每种方法在实时代码中查找的时间。
猜你喜欢
  • 1970-01-01
  • 2019-05-13
  • 2019-11-23
  • 2016-10-18
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多