假设有一个2列数据框,其中一列是时间或距离,按顺序递增,另一列是观测值,可能会有一些NA。如何有效地使用滑动窗口函数,在持续时间为X(例如5秒)的窗口中获取某些统计信息,例如平均值,在Y秒(例如2.5秒)内滑动窗口,重复此过程...窗口中的观测数量基于时间列,因此每个窗口中的观测数量和滑动窗口的观测数量都可能不同该函数应接受任何窗口大小,最多到观测数,并具有步长。
解释:在期望的输出中,第一个窗口查找-2.5到2.5之间的时间。该窗口内有一次测量观察值,并且它不是NA,因此我们得到观察值1.0222694。下一个窗口是从0到5,窗口内有一个NA,所以我们得到NA。对于从2.5到7.5的窗口也是如此。下一个窗口是从5到10。窗口内有5个观察值,没有一个是NA。因此,我们得到这5个观察值的平均值(即mean(dat[dat$time>5&dat$time<10,'measure']))。
我尝试过的方法:以下是我针对步长为窗口持续时间的1/2的特定情况所尝试的方法:
以下是样本数据(请参见“ 编辑:”以获取更大的样本集)
set.seed(42)
dat <- data.frame(time = seq(1:20)+runif(20,0,1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:19,2)] <- NA_real_
head(dat)
time measure
1 1.914806 1.0222694
2 2.937075 0.3490641
3 3.286140 NA
4 4.830448 0.8112979
5 5.641746 0.8773504
6 6.519096 1.2174924
期望输出针对5秒窗口、2.5秒步长、第一个窗口从-2.5到2.5的特定情况,na.rm=FALSE:
[1] 1.0222694
[2] NA
[3] NA
[4] 1.0126639
[5] 0.9965048
[6] 0.9514456
[7] 1.0518228
[8] NA
[9] NA
[10] NA
解释:在期望的输出中,第一个窗口查找-2.5到2.5之间的时间。该窗口内有一次测量观察值,并且它不是NA,因此我们得到观察值1.0222694。下一个窗口是从0到5,窗口内有一个NA,所以我们得到NA。对于从2.5到7.5的窗口也是如此。下一个窗口是从5到10。窗口内有5个观察值,没有一个是NA。因此,我们得到这5个观察值的平均值(即mean(dat[dat$time>5&dat$time<10,'measure']))。
我尝试过的方法:以下是我针对步长为窗口持续时间的1/2的特定情况所尝试的方法:
windo <- 5 # duration in seconds of window
# partition into groups depending on which window(s) an observation falls in
# When step size >= window/2 and < window, need two grouping vectors
leaf1 <- round(ceiling(dat$time/(windo/2))+0.5)
leaf2 <- round(ceiling(dat$time/(windo/2))-0.5)
l1 <- tapply(dat$measure, leaf1, mean)
l2 <- tapply(dat$measure, leaf2, mean)
as.vector(rbind(l2,l1))
不灵活,不优雅,不高效。如果步长不是1/2窗口大小,那么这种方法就行不通。
对于这种问题,您有什么通用解决方案的想法吗?任何解决方案都可以接受。速度越快越好,但我更喜欢使用基本R、数据表、Rcpp和/或并行计算的解决方案。在我的真实数据集中,有几百万个观察结果存储在数据框列表中(最大数据框约为400,000个观察结果)。
以下是附加信息: 更大的样本集
编辑:根据要求,这里有一个更大、更现实的示例数据集,其中包含许多NA和最小时间跨度(~0.03)。确切地说,数据框列表包含像上面那个小数据框一样的小数据框,以及像下面这样的更大的数据框:
set.seed(42)
dat <- data.frame(time = seq(1:50000)+runif(50000, 0.025, 1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:50000,1000)] <- NA_real_
dat$measure[c(350:450,3000:3300, 20000:28100)] <- NA_real_
dat <- dat[-c(1000:2000, 30000:35000),]
# a list with a realistic number of observations:
dat <- lapply(1:300,function(x) dat)
RcppRoll
;我会去看一下。至于您编写的函数,据我所知,窗口是基于观测数量而不是时间持续期间,这不是我想要的。 - Jota