微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

基于 R 中的备用列,跨数据帧的均值滑动窗口

如何解决基于 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 举报,一经查实,本站将立刻删除。