如何在Python中简单地计算时间序列的滚动/移动方差?

8nuwlpux  于 2023-05-05  发布在  Python
关注(0)|答案(7)|浏览(213)

我有一个简单的时间序列,我正在努力估计一个移动窗口内的方差。更具体地说,我无法弄清楚一些与实现滑动窗口功能的方式有关的问题。例如,当使用NumPy且窗口大小= 20时:

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) 

rolling_window(data, 20)
np.var(rolling_window(data, 20), -1)
datavar=np.var(rolling_window(data, 20), -1)

也许我在某个地方错了,在这条思路上。有人知道一个简单的方法来做到这一点吗?任何帮助/建议将是最受欢迎的。

mwecs4sa

mwecs4sa1#

Pandas rolling_meanrolling_std函数已被弃用,并被更通用的“滚动”框架取代。@elyase的例子可以修改为:

import pandas as pd
import numpy as np
%matplotlib inline

# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()

#plot the time series
ts.plot(style='k--')

# calculate a 60 day rolling mean and plot
ts.rolling(window=60).mean().plot(style='k')

# add the 20 day rolling standard deviation:
ts.rolling(window=20).std().plot(style='b')

rolling函数支持许多不同的窗口类型,如here所述。可以在rolling对象上调用许多函数,包括var和其他有趣的统计数据(skewkurtquantile等)。我坚持使用std,因为图与平均值在同一个图上,这在单位方面更有意义。

gdx19jrr

gdx19jrr2#

你应该看看pandas。例如:

import pandas as pd
import numpy as np

# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()

#plot the time series
ts.plot(style='k--')

# calculate a 60 day rolling mean and plot
pd.rolling_mean(ts, 60).plot(style='k')

# add the 20 day rolling variance:
pd.rolling_std(ts, 20).plot(style='b')

a8jjtwal

a8jjtwal3#

尽管这是一个旧线程,但我将添加另一个从this修改的方法,它不依赖pandas,也不依赖python循环。从本质上讲,使用numpy的stride技巧,您可以首先创建一个具有striding的数组视图,以便沿着最后一个轴计算函数的统计量相当于执行滚动统计量。我修改了原始代码,通过填充添加最后一个轴的开始,使输出形状与输入形状相同。

import numpy as np

def rolling_window(a, window):
    pad = np.ones(len(a.shape), dtype=np.int32)
    pad[-1] = window-1
    pad = list(zip(pad, np.zeros(len(a.shape), dtype=np.int32)))
    a = np.pad(a, pad,mode='reflect')
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

a = np.arange(30).reshape((5,6))

# rolling mean along last axis
np.mean(rolling_window(a, 3), axis=-1)

# rolling var along last axis
np.var(rolling_window(a, 3), axis=-1)

# rolling median along last axis
np.median(rolling_window(a, 3), axis=-1)
xkftehaa

xkftehaa4#

在我看来,将Pandas用于纯数字数据有点矫枉过正;Bottleneck工作得很好,但自2021年1月以来一直没有更新,并且不再适用于Python 3.9及更新版本;所以我将发布一个基于Josh Albert's version的版本,记住关于lib.stride_tricks.as_strided的文档说明,使用它可能不安全。
你可以使用NumPy的lib.stride_tricks.sliding_window_view(),它基本上是lib.stride_tricks.as_strided的安全(ish) Package 器,创建一个具有窗口大小的额外轴的数组(在任何维度上),允许你使用NumPy的内置统计函数在该轴上操作:

import numpy as np

window = 3  # size of the window
A = np.arange(10)

Aw = np.lib.stride_tricks.sliding_window_view(A, window)
Avar = np.var(Aw, axis=-1)

Avar
>>> array([0.66666667, 0.66666667, 0.66666667, 0.66666667, 0.66666667,
       0.66666667, 0.66666667, 0.66666667])

当然,这也适用于meanmaxminstd等。
注意:据我所知,没有办法包括数组的“边”,即。A的开始和结束,其中不能获得全窗口长度。由此产生的阵列将被短接到可以达到完整窗口长度的部分,请参见返回的文档。

mwecs4sa

mwecs4sa5#

我只是在寻找相同的解决方案,并发现瓶颈包应该非常可靠和快速地完成任务。下面是来自www.example.com的稍微调整的示例https://kwgoodman.github.io/bottleneck-doc/reference.html#bottleneck.move_var:

>>> import bottleneck as bn
>>> a = np.array([1.0, 2.0, 3.0, np.nan, 5.0])
>>> bn.move_var(a, window=2)
array([ nan,  0.25,  0.25,  nan,  nan])
>>> bn.move_var(a, window=2, min_count=1)
array([ 0. ,  0.25,  0.25,  0. ,  0. ])

注意,所得方差对应于窗口的 last 索引。
该软件包可从Ubuntu repos,pip等获得。它可以在任意轴上运行,如numpy数组等。除此之外,它声称在许多情况下比plain-numpy实现更快。

8tntrjer

8tntrjer6#

这里有一个简单的方法来计算移动平均线(或时间窗口内的任何其他操作)使用普通Python。
您可以通过更改window变量中的值来更改时间窗口。例如,如果您想要一个30分钟的时间窗口,您可以将该数字更改为3000000000。
在本例中,条目保存在名为data的字典中。但是,您可以从任何适合您的集合中获取此数据。
你可以将结果保存到你喜欢的任何集合或数据库中。

data = {}

def one_min_avg():
    window = int(datetime.now().strftime("%H%M%S%f")) - 100000000
    history = {}
    for i in message_log.items():
        if i[0] >= window:
            history.update({i})
    for i in list(history):
        if i < window:
            history.pop(i)
    avg = sum(history.values()) / len(list(history))
    return avg

注意:您可能需要添加一些错误处理,以避免被零除或函数无法访问您的数据。

zwghvu4y

zwghvu4y7#

一个简单的方法来做(几乎)任何滚动/移动计算是做卷积!
在这种情况下,您可以将数据中的标准差公式与设置的窗口大小(ws)进行卷积。

moving_std = np.sqrt(np.convolve((data - np.mean(data))**2, np.ones(ws)/ws, mode='valid'))

只是不要忘记,当你绘制这个图时,moving_std的第一个点将向左移动ws空间,与你的数据相比,因为窗口大小。因此,您需要通过将窗口大小添加到x轴来解决这个问题。

相关问题