所以我想说我有一个载体
a <- rnorm(6000)
我想计算第一个值到第60个的平均值,然后再次计算第61个值到第120个的平均值,所以第四个。所以基本上我想计算每60个值的平均值,从该向量给出100个均值。我知道我可以做一个for循环,但我想知道是否有更好的方法来做到这一点?
答案 0 :(得分:8)
我会用
colMeans(matrix(a, 60))
.colMeans(a, 60, length(a) / 60) # more efficient (without reshaping to matrix)
对用户adunaic的请求进行了增强
仅当有60x100个数据点时才有效。如果你最后有一个不完整的60,那么这个错误。为其他人提供一个通用的解决方案来寻找这个问题是很好的。
BinMean <- function (vec, every, na.rm = FALSE) {
n <- length(vec)
x <- .colMeans(vec, every, n %/% every, na.rm)
r <- n %% every
if (r) x <- c(x, mean.default(vec[(n - r + 1):n], na.rm = na.rm))
x
}
a <- 1:103
BinMean(a, every = 10)
# [1] 5.5 15.5 25.5 35.5 45.5 55.5 65.5 75.5 85.5 95.5 102.0
采用分组操作的替代解决方案(效率较低)
BinMean2 <- function (vec, every, na.rm = FALSE) {
grp <- as.integer(ceiling(seq_along(vec) / every))
grp <- structure(grp, class = "factor",
levels = as.character(seq_len(grp[length(grp)])) )
lst <- .Internal(split(vec, grp))
unlist(lapply(lst, mean.default, na.rm = na.rm), use.names = FALSE)
}
<强>速度强>
library(microbenchmark)
a <- runif(1e+4)
microbenchmark(BinMean(a, 100), BinMean2(a, 100))
#Unit: microseconds
# expr min lq mean median uq max
# BinMean(a, 100) 40.400 42.1095 54.21286 48.3915 57.6555 205.702
# BinMean2(a, 100) 1216.823 1335.7920 1758.90267 1434.9090 1563.1535 21467.542
答案 1 :(得分:0)
另一种选择是通过创建分组变量来使用tapply
。
可以通过两种方式创建分组变量:
1)使用rep
tapply(a, rep(seq_along(a), each = n, length.out = length(a)), mean)
2)使用gl
tapply(a, gl(length(a)/n, n), mean)
如果将向量转换为数据帧/小节,我们可以使用相同的逻辑并计算mean
aggregate(a~gl(length(a)/n, n), data.frame(a), mean)
或与dplyr
library(dplyr)
tibble::tibble(a) %>%
group_by(group = gl(length(a)/n, n)) %>%
summarise(mean_val = mean(a))
数据
set.seed(1234)
a <- rnorm(6000)
n <- 60
答案 2 :(得分:0)
我建议使用sapply函数:
a <- rnorm(6000)
seq <- seq(1, length(a), 60)
a_mean <- sapply(seq, function(i) {mean(a[i:(i+59)])})