首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >潘达斯如何计算罩下的指数移动平均线?

潘达斯如何计算罩下的指数移动平均线?
EN

Stack Overflow用户
提问于 2018-10-12 16:20:17
回答 1查看 2K关注 0票数 1

我试图将熊猫EMA性能与南巴性能进行比较。

一般来说,如果熊猫已经与熊猫一起构建,我就不会编写函数,因为熊猫总是比我缓慢的手工编码的蟒蛇函数更快;例如分位数排序值等。我相信这是因为很多熊猫是用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的移动平均值的值,α是平滑的参数。

代码如下

代码语言:javascript
复制
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的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-12 19:42:39

但在这里,我感兴趣的是,在计算指数移动平均值方面,numba如何优于Pandas。

您的版本看起来更快,这完全是因为您传递给它的是一个NumPy数组,而不是Pandas数据结构:

代码语言:javascript
复制
>>> 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

代码语言:javascript
复制
>>> ewm = pd.DataFrame().ewm(alpha=0.1)
>>> type(ewm)
<class 'pandas.core.window.EWM'>

无论你是通过comspanhalflife,还是alpha,Pandas都会使用com并使用它。

当您调用方法本身(如ewm.mean() )时,它将映射到._apply(),在本例中,._apply()充当适当的Cython函数的路由器

代码语言:javascript
复制
cfunc = getattr(_window, func, None)

.mean()而言,func是"ewma“。_window是Cython模块pandas/libs/window.pyx

这就把您带到了事物的中心,在ewma()函数中,这是大部分工作发生的地方:

代码语言:javascript
复制
weighted_avg = ((old_wt * weighted_avg) +
                (new_wt * cur)) / (old_wt + new_wt)

如果您希望进行更公平的比较,请直接使用底层NumPy值调用此函数:

代码语言:javascript
复制
>>> 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()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52783479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档