从移动平均中提取数据点?


15

是否可以从移动平均数据中提取数据点?

换句话说,如果一组数据仅具有前30个点的简单移动平均值,是否可以提取原始数据点?

如果是这样,怎么办?


1
答案是肯定的,但是确切的过程取决于如何处理数据的初始段。如果只是删除它,则实际上已经丢失了15条数据,给您留下了不确定的线性方程组。结果是,通常存在许多有效答案,但是如果(a)将较短的窗口(或某些类似的过程)用于最初的15个移动平均线,或者(b)您可以在解决方案(约15个维度的约束值...)。你现在是什么情况
Whuber

@whuber非常感谢您的关注!我有2,000分。第一个MA点很可能是前30个原始点的平均值。准确性仅次于一般正确的结果,最准确的说是在最“最近”的时间点上的好猜测。您能推荐一种相对简单的方法吗?提前致谢!

1
(如果您花费超过五分钟的时间写评论...)。我想写的是,您可以将平均视为矩阵乘法。中间的行在对角线之前将具有1/30 * [1 1 1 ...]。问题是,如何处理矢量边界处的点以使矩阵可逆。您可以通过假设它们是对较少元素求平均值的结果来进行操作,或者您可以考虑其他约束。请注意,虽然矩阵求逆是一种易于理解的方法,但它并不是最有效的方法。您可能要使用FFT来做到这一点。
fabee

Answers:


4

+1是fabee的答案,这是完整的。只是根据我发现可以进行手头操作的软件包,将其转换为R的注释。就我而言,我的数据是三个月的NOAA温度预测:1月-2月-3月,2月-3月-4月,3月-4月-5月等,我想将其分解为(近似)假设每个三个月的温度基本上是一个平均值,则为月度值。

library (Matrix)
library (matrixcalc)

# Feb-Mar-Apr through Nov-Dec-Jan temperature forecasts:

qtemps <- c(46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2)

# Thus I need a 10x12 matrix, which is a band matrix but with the first
# and last rows removed so that each row contains 3 1's, for three months.
# Yeah, the as.matrix and all is a bit obfuscated, but the results of
# band are not what svd.inverse wants.

a <- as.matrix (band (matrix (1, nrow=12, ncol=12), -1, 1)[-c(1, 12),])
ai <- svd.inverse (a)

mtemps <- t(qtemps) %*% t(ai) * 3

这对我来说很棒。谢谢@fabee。

编辑:好的,将我的R反向翻译为Python,我得到:

from numpy import *
from numpy.linalg import *

qtemps = transpose ([[46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2]])

a = tril (ones ((12, 12)), 2) - tril (ones ((12, 12)), -1)
a = a[0:10,:]

ai = pinv (a)

mtemps = dot (ai, qtemps) * 3

(调试所需的时间比R版本要长得多。首先是因为我不像R那样熟悉Python,还因为R在交互方面更有用。)


@Gracchus:对不起,不是C ++的人,但是您可以在Armadillo C ++线性代数库(arma.sourceforge.net)中找到所需的东西,该库也可以通过RcppArmadillo包在R中获得。
韦恩,2013年

确定,看看是否适合您。如果是这样,您可以选择我的答案;-)
韦恩(Wayne)

FYI在Python中的最佳做法是进行绝对导入:python.org/dev/peps/pep-0008/#imports使得阅读他人的代码非常容易,因为您实际上知道函数的来源,而不必知道查找您不认识的每个人。希望这是R的标准操作。不得不查找别人代码中的每个小功能确实让我
感到烦恼

另外,用于Python交互性或IPython的Jupyter笔记本。
wordforthewise

17

我试着把胡言乱语的答案。假设您有一个大向量其中n = 2000个条目。如果计算的移动平均值与长度的窗口= 30,则可以写为一个向量矩阵乘法Ŷ = X的向量X与矩阵Xñ=2000=30y=Axx

A=130(1.1个0001个1个001个1个0001个1个

其中有个将随着您在行中的移动而移动,直到30个到达矩阵的末尾。此处,平均向量y具有1970维。矩阵有1970行和2000列。因此,它不是不可逆的。3030ÿ1970年2000

如果你不熟悉的矩阵,想想它作为一个线性方程组:您正在搜索的变量,则前三十个平均值y 1,后二十个平均值y 2,依此类推。X1个X2000ÿ1个ÿ2

方程系统(和矩阵)的问题在于,它比方程具有更多的未知数。因此,你不能唯一地识别您的未知数。直观的原因是您在求平均值时放宽了尺寸,因为x的前三十个尺寸在y中没有得到对应的元素,因为您无法将求平均值窗口移到x之外。X1个XñXÿX

一种使或等价的方程组可求解的方法是,提出30个以上的方程(或A的30个行),这些方程可提供附加信息(与A的所有其他行线性独立)。一种3030一种一种

另外,也许更容易,方法是使用伪逆一个。这将生成向量z = A y,该向量的维数与x相同,并且具有使yA z之间的二次距离最小的特性(请参阅Wikipedia)。一种一种ž=一种ÿXÿ一种ž

2000X

使用伪逆从移动平均值重构原始信号

许多数值程序提供伪逆(例如Matlab,python中的numpy等)。

这是从我的示例生成信号的python代码:

from numpy import *
from numpy.linalg import *
from matplotlib.pyplot import *
# get A and its inverse     
A = (tril(ones((2000,2000)),-1) - tril(ones((2000,2000)),-31))/30.
A = A[30:,:]
pA = pinv(A) #pseudo inverse

# get x
x = random.randn(2000) + 5
y = dot(A,x)

# reconstruct
x2 = dot(pA,y)

plot(x,label='original x')
plot(y,label='averaged x')
plot(x2,label='reconstructed x')
legend()
show()

希望能有所帮助。


这是一个很好的答案,但是当您说“它最小化了y和Az之间的二次距离”时,我认为您是错误的。实际上,y和Az是同一件事。最小化的是z的范数,该范数对我尝试过的现实世界信号效果很好,但如果您的原始信号有很多异常值,则效果不是很好。
gdelfino

我不确定是否跟随。y和Ax是同一件事,但y和Az不是同一件事,这确实使z的范数最小。我也看不到为什么它不适用于我的示例。蓝色和红色线条非常吻合。我在您的留言中遗漏了什么吗?
fabee

y是从原始信号x乘以A得出的移动平均值。此过程为我们提供了具有相同移动平均值y的信号z。因此y = Az因此,只有z的范数最小。如果原始信号碰巧具有较大的范数值,则该过程将不会产生良好的结果。以下是具有较大范数值的示例信号:
gdelfino

{42.8,-33.7、13.2,-45.6、10.2、35.8,-41.4、20.253、43.3429,-33.2735、13.6135,-45.1067、10.6346、36.1352,-40.9703、20.6616、43.6796,-32.8966、14.0406,-44.7001、10.9988 ,36.4675,-40.7277、20.8823、43.7878,-32.7415、13.9951,-44.7947、11.044、36.3873,-40.7117、20.0755、43.8204,-32.9399、13.9129,-44.9549、10.8703、36.1559,-40.8894、20.4211、43.4591,-36.3786 ,13.5468,-45.2374、10.3787、35.8235,-41.5161、19.9717、43.0658,-33.7125、13.0321}
gdelfino

请为以上信号使用8号窗口。这样,滤波后的信号在形状上与原始信号非常不同。
gdelfino
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.