一般来说,如果熊猫已经与熊猫一起构建,我就不会编写函数,因为熊猫总是比我缓慢的手工编码的蟒蛇函数更快;例如分位数、排序值等。我相信这是因为很多熊猫是用C编写的,而且由于矢量化,熊猫的.apply()方法比显式的蟒蛇要快得多(但如果这不是真的,我愿意解释一下)。但是在这里,对于计算EMA,我发现使用numba远远超过了熊猫。
我所编码的EMA是由
S_t = Y_1,t=1
S_t = alpha*Y_t + (1 -α)*S_{t-1},t>1
其中Y_t是时间t的时间序列的值,S_t是时间t的移动平均值的值,α是平滑的参数。
代码如下
from numba import jit
import pandas as pd
import numpy as np
@jit
def ewm(arr, alpha):
"""
Calculate the EMA of an array arr
:param arr: numpy array of floats
:param alpha: float between 0 and 1
:return: numpy array of floats
"""
# initialise ewm_arr
ewm_arr = np.zeros_like(arr)
ewm_arr[0] = arr[0]
for t in range(1,arr.shape[0]):
ewm_arr[t] = alpha*arr[t] + (1 - alpha)*ewm_arr[t-1]
return ewm_arr
# initialize array and dataframe randomly
a = np.random.random(10000)
df = pd.DataFrame(a)
%timeit df.ewm(com=0.5, adjust=False).mean()
>>> 1000 loops, best of 3: 1.77 ms per loop
%timeit ewm(a, 0.5)
>>> 10000 loops, best of 3: 34.8 µs per loop我们看到,手编码的ewm函数比熊猫的ewm方法快50倍左右。
numba也可能会表现出比其他熊猫更好的方法,这取决于人们如何编码它们的功能。但在这里,我感兴趣的是numba在计算指数移动平均值方面如何优于熊猫。熊猫在做什么(不做),这会让它变慢--或者在这种情况下,numba的速度太快了吗?熊猫是如何计算引擎盖下的EMA的?
发布于 2018-10-12 19:42:39
但在这里,我感兴趣的是,在计算指数移动平均值方面,numba如何优于Pandas。
您的版本看起来更快,这完全是因为您传递给它的是一个NumPy数组,而不是Pandas数据结构:
>>> s = pd.Series(np.random.random(10000))
>>> %timeit ewm(s, alpha=0.5)
82 ms ± 10.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit ewm(s.values, alpha=0.5)
26 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit s.ewm(alpha=0.5).mean()
852 µs ± 5.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)一般来说,将NumPy和Pandas的操作进行比较是无稽之谈.后者建立在前者之上,几乎总是以速度换取灵活性。(但是,考虑到这一点,Pandas的速度仍然很快,而且随着时间的推移,对Cython的依赖程度也越来越高。)我不确定numba/jit在NumPy中表现得更好是什么。但是如果你用Pandas系列来比较这两种功能,Pandas本身就会更快。
潘达斯是如何计算引擎盖下的电磁干扰的?
当您调用df.ewm() (尚未调用.mean()或.cov()等方法)时,中间结果是在pandas/core/window.py中找到的真正的类EWM。
>>> ewm = pd.DataFrame().ewm(alpha=0.1)
>>> type(ewm)
<class 'pandas.core.window.EWM'>无论你是通过com,span,halflife,还是alpha,Pandas都会使用com并使用它。
当您调用方法本身(如ewm.mean() )时,它将映射到._apply(),在本例中,._apply()充当适当的Cython函数的路由器:
cfunc = getattr(_window, func, None)就.mean()而言,func是"ewma“。_window是Cython模块pandas/libs/window.pyx。
这就把您带到了事物的中心,在ewma()函数中,这是大部分工作发生的地方:
weighted_avg = ((old_wt * weighted_avg) +
(new_wt * cur)) / (old_wt + new_wt)如果您希望进行更公平的比较,请直接使用底层NumPy值调用此函数:
>>> from pandas._libs.window import ewma
>>> %timeit ewma(s.values, 0.4, 0, 0, 0)
513 µs ± 10.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)(请记住,它只需要一个com;为此,您可以使用pandas.core.window._get_center_of_mass()。
https://stackoverflow.com/questions/52783479
复制相似问题