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

Posted

技术标签:

【中文标题】基于 R 中的备用列,跨数据帧的均值滑动窗口【英文标题】:Sliding window of mean across dataframe, based on alternate column in R 【发布时间】:2021-08-31 14:33:20 【问题描述】:

我希望使用滑动窗口方法计算变量的平均值,但要基于数据框中另一列的值。这很难解释……

以这个示例数据框为例:

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")

然而,这并不是我想要的。当df$dist 的范围从1-50 然后25-75 然后50-100 等等时,我想计算mean(df$value)

上面没有这样做,因为在我的数据集中我不能假设df$dist 系统地计数(即不会错过随机数)。因此,简单地应用一个窗口向下移动一定数量的行会产生不正确的结果。

任何关于我将如何解决这个问题的建议都很棒。

提前谢谢你。

【问题讨论】:

【参考方案1】:

这里有几种选择。 (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, width, df, mean),
   N = sapply(starts, Fun, width, df, 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, width, fun, step) 
  fun2 <- function(x) fun(na.omit(x))
  rollapply(x, width, 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, 
  ends = starts + width - 1,
  mean = roll(m$value, width, mean, step),
  N = roll(m$value, width, 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, max(df$dist), 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)

【讨论】:

非常感谢@G。格洛腾迪克这看起来正是我所追求的。有没有办法在mean 函数中也包含na.rm=T?看看这个脚本,这也适用于每个距离的多个观测?再次感谢您 也很抱歉忘记set.seed() 我最初使用了 na.rm = TRUE 但后来似乎因为我们同时考虑了平均值和长度,因此将其分解出来更有意义。您可以提供一个 function(x) mean(x, na.rm = TRUE) 和 function(x) length(na.omit(x)) 来滚动然后直接使用它而不是定义 fun2 但这会扩展代码。 好的,非常感谢您非常全面和有用的回答。赞成并接受 - 祝您有美好的一天!

以上是关于基于 R 中的备用列,跨数据帧的均值滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章

基于索引的非重叠滑动窗口

matlab上有滑动平均的函数吗?

如何在熊猫数据框中创建滑动窗口并应用函数

pandas计算滑动窗口中的最小值实战(Rolling Minimum in a Pandas Column):计算单数据列滑动窗口中的最小值计算多数据列滑动窗口中的最小值

pandas计算滑动窗口中的中位数实战(Rolling Median of a Pandas Column):计算单数据列滑动窗口中的中位数计算多数据列滑动窗口中的中位数

pandas计算滑动窗口中的最大值实战(Rolling Maximum in a Pandas Column):计算单数据列滑动窗口中的最大值计算多数据列滑动窗口中的最大值