如何像pandas数据帧一样快速访问numpy数组

时间:2016-05-20 00:54:56

标签: python numpy pandas

我对几种访问DataFrame数据的方法进行了比较。见下面的结果。最快的访问是在get_value上使用DataFrame方法。我在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

1 个答案:

答案 0 :(得分:2)

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