小编典典

数字处理二维数组的最快方法:数据框vs系列vs数组vs numba

python

编辑添加:我认为numba基准不公平,以下注意事项

我正在尝试对以下用例进行数值处理数据的不同方法的基准测试:

  1. 相当大的数据集(超过100,000条记录)
  2. 100行以上相当简单的代码(z = x + y)
  3. 不需要排序或索引
    换句话说,不需要序列和数据框的全部通用性,尽管它们在此处包含在b / c中,它们仍然是封装数据的便捷方法,并且通常存在预处理或后处理,这确实需要熊猫的通用性。 numpy数组。

问题:根据此用例,以下基准是否合适?如果不合适,如何改进它们?

# importing pandas, numpy, Series, DataFrame in standard way
from numba import jit
nobs = 10000
nlines = 100

def proc_df():
   df = DataFrame({ 'x': np.random.randn(nobs),
                    'y': np.random.randn(nobs) })
   for i in range(nlines):
      df['z'] = df.x + df.y
   return df.z

def proc_ser():
   x = Series(np.random.randn(nobs))
   y = Series(np.random.randn(nobs))
   for i in range(nlines):
      z = x + y
   return z

def proc_arr():
   x = np.random.randn(nobs)
   y = np.random.randn(nobs)
   for i in range(nlines):
      z = x + y
   return z

@jit
def proc_numba():
   xx = np.random.randn(nobs)
   yy = np.random.randn(nobs)
   zz = np.zeros(nobs)
   for j in range(nobs):
      x, y = xx[j], yy[j]
      for i in range(nlines):
         z = x + y
      zz[j] = z
   return zz

结果(Win 7,具有3年历史的Xeon工作站(四核)。标准和近期的Anaconda分布非常接近。)

In [1251]: %timeit proc_df()
10 loops, best of 3: 46.6 ms per loop

In [1252]: %timeit proc_ser()
100 loops, best of 3: 15.8 ms per loop

In [1253]: %timeit proc_arr()
100 loops, best of 3: 2.02 ms per loop

In [1254]: %timeit proc_numba()
1000 loops, best of 3: 1.04 ms per loop   # may not be valid result (see note below)

编辑以将df / series / array传递到函数中而不是在函数内部创建它们(例如,将包含“ randn”的代码行从内部函数移至外部函数)以添加(响应jeff)替代结果:

10 loops, best of 3: 45.1 ms per loop
100 loops, best of 3: 15.1 ms per loop
1000 loops, best of 3: 1.07 ms per loop
100000 loops, best of 3: 17.9 µs per loop   # may not be valid result (see note below)

关于numba结果的注释:我认为numba编译器必须在for循环上进行优化,并将for循环减少为单个迭代。我不知道,但这是我能提出的唯一解释,因为它不能比numpy快50倍,对吗?后续问题在这里: 为什么numba比numpy快?


阅读 234

收藏
2021-01-20

共1个答案

小编典典

好吧,您实际上不是在这里安排相同的时间(或者,您正在安排不同的方面)。

例如

In [6]:    x = Series(np.random.randn(nobs))

In [7]:    y = Series(np.random.randn(nobs))

In [8]:  %timeit x + y
10000 loops, best of 3: 131 µs per loop

In [9]:  %timeit Series(np.random.randn(nobs)) + Series(np.random.randn(nobs))
1000 loops, best of 3: 1.33 ms per loop

因此,[8]乘以实际运算,而[9]包括序列创建(和随机数生成)的开销加上实际运算

另一个例子是proc_serVS proc_df。这proc_df包括在DataFrame中分配特定列的开销(这对于初始创建和后续重新分配实际上是不同的)。

因此,创建结构(您也可以为其计时,但这是一个单独的问题)。执行完全相同的操作并计时。

此外,您说不需要对齐。pandas默认为您提供此功能(没有简单的方法将其关闭,尽管仅需简单检查它们是否已对齐)。在numba中时,您需要“手动”对齐它们。

2021-01-20