函数或循环到 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
我不熟悉 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