我有一个值向量,我想用较小的幻灯片报告窗口中的平均值。
例如,对于具有以下值的向量:
4, 5, 7, 3, 9, 8
窗口大小为3,幻灯片大小为2,将执行以下操作:
(4+5+7)/3 = 5.33
(7+3+9)/3 = 6.33
(9+8)/3 = 5.67
并返回这些值的向量:
5.33, 6.33, 5.67
有没有一个简单的函数可以帮我做到这一点?如果它还返回窗口开始的索引,那将是一个额外的好处。在此示例中,该值为1,3,5
我有一个值向量,我想用较小的幻灯片报告窗口中的平均值。
例如,对于具有以下值的向量:
4, 5, 7, 3, 9, 8
窗口大小为3,幻灯片大小为2,将执行以下操作:
(4+5+7)/3 = 5.33
(7+3+9)/3 = 6.33
(9+8)/3 = 5.67
并返回这些值的向量:
5.33, 6.33, 5.67
有没有一个简单的函数可以帮我做到这一点?如果它还返回窗口开始的索引,那将是一个额外的好处。在此示例中,该值为1,3,5
Answers:
rollapply
软件包zoo中的函数使您接近:
> require(zoo)
> TS <- zoo(c(4, 5, 7, 3, 9, 8))
> rollapply(TS, width = 3, by = 2, FUN = mean, align = "left")
1 3
5.333333 6.333333
它不会为您计算最后一个值,因为它不包含3个观察值。也许这足以解决您的实际问题?另外,请注意,返回的对象具有您想要的索引作为names
返回的向量。
您的示例假设最后一个窗口中存在不可观察的0。加上NA
来代表缺失的信息并告诉mean
处理缺失的值可能更有用或更现实。在这种情况下,我们将(8 + 9)/ 2作为我们的最终窗口值。
> TS <- zoo(c(4, 5, 7, 3, 9, 8, NA))
> rollapply(TS, width = 3, by = 2, FUN = mean, na.rm = TRUE, align = "left")
1 3 5
5.333333 6.333333 8.500000
na.rm = TRUE
参数传递给mean
。答案将与OP要求的答案不同,但似乎更有用。我将编辑答案以包括此内容。
Rollapply适用于小型数据集。但是,如果您要处理几百万行(基因组),则速度会很慢。
以下功能超级快。
data <- c(runif(100000, min=0, max=.1),runif(100000, min=.05, max=.1),runif(10000, min=.05, max=1), runif(100000, min=0, max=.2))
slideFunct <- function(data, window, step){
total <- length(data)
spots <- seq(from=1, to=(total-window), by=step)
result <- vector(length = length(spots))
for(i in 1:length(spots)){
result[i] <- mean(data[spots[i]:(spots[i]+window)])
}
return(result)
}
http://coleoguy.blogspot.com/2014/04/sliding-window-analysis.html
-1
(添加到范围)和a +1
(添加到循环),否则window = 3将返回4个(!)值的平均值。
这行简单的代码可以完成以下任务:
((c(x,0,0) + c(0,x,0) + c(0,0,x))/3)[3:(length(x)-1)]
如果x
是所讨论的向量。
library(zoo)
x=c(4, 5, 7, 3, 9, 8)
rollmean(x,3)
要么
library(TTR)
x=c(4, 5, 7, 3, 9, 8)
SMA(x,3)
shabbychef在R中的答案:
slideMean<-function(x,windowsize=3,slide=2){
idx1<-seq(1,length(x),by=slide);
idx1+windowsize->idx2;
idx2[idx2>(length(x)+1)]<-length(x)+1;
c(0,cumsum(x))->cx;
return((cx[idx2]-cx[idx1])/windowsize);
}
编辑:您正在寻找的索引只是idx1
...此函数可以轻松修改以也返回它们,但是通过再次调用来重新创建它们几乎一样快seq(1,length(x),by=slide)
。
fromo::running_mean
从fromo软件包的最新版本中使用。
当您对我投反对票时,我可以在Matlab和Duck中轻松完成此操作:
%given vector x, windowsize, slide
idx1 = 1:slide:numel(x);
idx2 = min(numel(x) + 1,idx1 + windowsize); %sic on +1 here and no -1;
cx = [0;cumsum(x(:))]; %pad out a zero, perform a cumulative sum;
rv = (cx(idx2) - cx(idx1)) / windowsize; %tada! the answer!
作为副作用,idx1
是元素在总和中的索引。我相信这可以很容易地翻译成first:skip:last
R。Matlab中的惯用法使数组为first,first + skip,first + 2skip,...,first + n skip,其中数组的最后一个元素不大于last
。
编辑:我已经省略了平均部分(除以windowsize
)。
这将为您提供窗口平均值和窗口第一个值的索引:
#The data
x <- c(4, 5, 7, 3, 9, 8)
#Set window size and slide
win.size <- 3
slide <- 2
#Set up the table of results
results <- data.frame(index = numeric(), win.mean = numeric())
#i indexes the first value of the window (the sill?)
i <- 1
#j indexes the row of the results to be added next
j <- 1
while(i < length(x)) {
#This mean preserves the denominator of 3
win.mean <- sum(x[i:(i+2)], na.rm = TRUE)/win.size
#Insert the results
results[j, ] <- c(i, win.mean)
#Increment the indices for the next pass
i <- i + slide
j <- j + 1
}
各种注意事项适用:除了样本数据外,没有针对任何其他情况进行过测试;我相信,如果您有很多值,那么像这样添加到数据帧会变得非常慢(因为它每次都会复制data.frame);等等。但是它确实产生了您所要求的。
rollapply
而是更容易理解和理解其意图的单线性。另外,rollapply
检查它的代码的目光可能比我一个下午准备的东西多得多。马课程。
[i:(i+2)]
为[i:(i+win.size-1)]
将使代码更通用。