如何解决基于 R 中的备用列,跨数据帧的均值滑动窗口
我希望使用滑动窗口方法计算变量的平均值,但基于数据框中另一列的值。很难解释所以...
以这个示例数据框为例:
dist <- c(seq(1,100,by=1),seq(101,200,by=2))
value<- runif(150,min=0,max=10)
df <- as.data.frame(cbind(dist,value))
head(df)
我知道我可以用下面的代码计算滑动窗口的平均值:
zoo::rollapply(df$value,width=50,by=25,FUN=mean,na.rm=TRUE,align="left")
然而,这不是我想要的。我想计算 mean(df$value)
当 df$dist
范围从 1-50
然后 25-75
然后 50-100
等等。
上面没有这样做,因为在我的数据集中我不能假设 df$dist
系统地计数(即不会遗漏随机数)。因此,简单地应用一个向下移动一定行数的窗口会产生不正确的结果。
关于我将如何处理这个问题的任何建议都很棒。
提前致谢。
解决方法
这里有几个选择。 (1) 没有包依赖,(2) 使用 rollapply,因此与问题中的代码最相似,(3) 使用 SQL 并且是最短的代码。
1) Base R 如果问题是 dist 不包含 1 和最大值之间的所有数字,那么我们可以像这样迭代间隔:
Fun <- function(st,width,df,fun) {
fun(subset(df,dist >= st & dist <= st + width - 1)$value)
}
width <- 50
step <- 25
starts <- seq(1,max(df$dist),step)
data.frame(starts,ends = starts + width - 1,mean = sapply(starts,Fun,mean),N = sapply(starts,length))
给予:
starts ends mean N
1 1 50 5.200910 50
2 26 75 4.710030 50
3 51 100 4.770270 50
4 76 125 4.880030 38
5 101 150 5.318415 25
6 126 175 5.575938 25
7 151 200 4.989383 25
8 176 225 3.918574 12
2) rollapply 另一种方法是扩展输入数据框,在这种情况下我们可以使用 rollapply。
library(zoo)
roll <- function(x,fun,step) {
fun2 <- function(x) fun(na.omit(x))
rollapply(x,by = step,fun2,partial = TRUE,align = "left")
}
width <- 50
step <- 25
m <- merge(df,data.frame(dist = 1:max(df$dist)),all = TRUE)
data.frame(starts,mean = roll(m$value,mean,step),N = roll(m$value,length,step)
)
给予:
starts ends mean N
1 1 50 5.200910 50
2 26 75 4.710030 50
3 51 100 4.770270 50
4 76 125 4.880030 38
5 101 150 5.318415 25
6 126 175 5.575938 25
7 151 200 4.989383 25
8 176 225 3.918574 12
3) sqldf 这可以使用带有指定左连接的 SQL 紧凑地表述。
library(sqldf)
width <- 50
step <- 25
starts <- data.frame(starts = seq(1,step))
fn$sqldf("select starts,starts+$width-1 ends,avg(value) mean,count(value) N
from starts
left join df on dist between starts and ends
group by starts.rowid")
给予:
starts ends mean N
1 1 50 5.200910 50
2 26 75 4.710030 50
3 51 100 4.770270 50
4 76 125 4.880030 38
5 101 150 5.318415 25
6 126 175 5.575938 25
7 151 200 4.989383 25
8 176 225 3.918574 12
注意
为了使输入可重现,我们必须在使用任何随机数之前设置种子,因此在上面我们使用了这个:
set.seed(123)
dist <- c(seq(1,100,by = 1),seq(101,200,by = 2))
value <- runif(150,min = 0,max = 10)
df <- data.frame(dist,value)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。