函数或循环到 R 中的子集移动平均线

Function or loop to subset moving average in R

我不熟悉 R 中的循环和函数。

假设我对四个样本(A、B、C、D)从 1.0 到 3.5 每 0.1 个单位进行测量。

我想找到 1.5、2.5 和 3.5 附近的平均测量值(+/- 0.2 单位)。因此,对于 1.5,我对 c(1.3、1.4、1.5、1.6 和 1.7)等处的值取平均值

我如何编写语句来总结所有四个样本的这三个平均值?我认为它可能会像这样开始:

X <- (1.5, 2.5, 3.5)

for (i in X)

{
  avg <- colMeans(subset(data,data$measurement > (i - 0.2) & data$measurement < (i + 0.2)))   
}

我也考虑过使用 '[' 代替:

colMeans(data[data$measurement > (i-0.2) & data$measurement < (i+0.2)]) 

感谢到目前为止的帮助,sqldf 是一个非常好的工具,这个例子正是我想要的!

但是,我无法让它与真实数据集一起工作。我修改了代码,使其看起来像(抱歉,这不再与示例数据集对应):

M <- sqldf("select r.i,avg(w.X1),avg(w.X2),avg(w.X3),avg(w.X4)
           from Y r, Y w
           where w.i betreen r.i - 1 and r.i + 1
           group by r.i
           having r.i+0.0 in (600, 700, 800)")

为了将其上下文化,我试图总结 599-601、699-701 和 799-801 中所有点的平均值,用于名为 X1、X2、X3、X4 的四列。我将这个数据框命名为 'Y'。这些行实际上是波长,数据指向在该波长反射的光量。

你看到上面的代码有什么问题吗? -- 它创建了一个具有正确维度的矩阵,但平均值与较大数据集中的平均值不匹配。我想知道我是否不理解代码中的某些内容,例如 'w' 变量的重要性。

正确的索引比循环更快。

library(zoo)
set.seed(1)
x <- as.character(seq(1,3.5,.1)) 
z <- zoo(data.frame(a=rnorm(length(x)),
                    b=rnorm(length(x)),
                    c=rnorm(length(x))),
         x)
z2 <- rollmean(z, k = 5, align = "center")[as.character(seq(1,3.5,.5)),]
> z2
              a           b          c
1.5  0.46601479  0.40153999  0.2007418
2    0.31015536 -0.22912642  0.4673692
2.5 -0.04141133  0.31978341  0.4350507
3    0.63816023 -0.07509644 -0.3622883

> data.frame(z2, index = index(z2))
              a           b          c index
1.5  0.46601479  0.40153999  0.2007418   1.5
2    0.31015536 -0.22912642  0.4673692     2
2.5 -0.04141133  0.31978341  0.4350507   2.5
3    0.63816023 -0.07509644 -0.3622883     3

如果你想要在 window 宽度小于 5 的边缘进行部分填充:

> rollapply(z, width = 5, align = "center", partial = TRUE, FUN = mean)[as.character(seq(1,3.5,.5)),]
              a           b           c
1   -0.42614637 -0.70156598  0.21492677
1.5  0.46601479  0.40153999  0.20074176 
2    0.31015536 -0.22912642  0.46736921 
2.5 -0.04141133  0.31978341  0.43505071
3    0.63816023 -0.07509644 -0.36228832
3.5 -0.47521823  0.22239574 -0.05024676

如果 windows 尺寸不规则,但如评论中所述等间距:

> z2 <- as.data.frame(z)
> z2$i <- row.names(z2)
> library(sqldf)
> sqldf("select a.i,avg(b.a),avg(b.b),avg(b.c) 
         from z2 a, z2 b 
         where b.i between a.i - .21 and a.i + .21 
         group by a.i 
         having a.i+0.0 in (1.5,2.0,2.5,3.0,3.5)")
    i    avg(b.a)    avg(b.b)    avg(b.c)
1 1.5  0.46601479  0.40153999  0.20074176
2   2  0.31015536 -0.22912642  0.46736921
3 2.5 -0.04141133  0.31978341  0.43505071
4   3  0.63816023 -0.07509644 -0.36228832
5 3.5 -0.47521823  0.22239574 -0.05024676