【问题标题】:calculating mean for every n values from a vector计算向量中每 n 个值的平均值
【发布时间】:2017-09-23 22:53:42
【问题描述】:

假设我有一个向量

a <- rnorm(6000)

我想计算第 1 个值到第 60 个值的平均值,然后再次计算第 61 个值到第 120 个值的平均值,以此类推。所以基本上我想计算每 60 个值的平均值,给我 100 个来自该向量的平均值。我知道我可以做一个 for 循环,但我想知道是否有更好的方法来做到这一点?

【问题讨论】:

  • 你可能会很高兴看看apply()函数
  • apply 函数主要适用于数据帧/矩阵。我在这里问一个向量。

标签: r vector mean


【解决方案1】:

我会用

 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

【讨论】:

    【解决方案2】:

    我推荐sapply

    a <- rnorm(6000)
    seq <- seq(1, length(a), 60)
    a_mean <- sapply(seq, function(i) {mean(a[i:(i+59)])})
    

    【讨论】:

      【解决方案3】:

      另一种选择是通过创建分组变量来使用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)
      

      如果我们将向量转换为 dataframe/tibble,我们可以使用相同的逻辑并计算 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
      

      【讨论】:

        猜你喜欢
        • 2018-05-05
        • 2021-12-18
        • 1970-01-01
        • 2021-11-08
        • 1970-01-01
        • 1970-01-01
        • 2019-01-05
        • 1970-01-01
        相关资源
        最近更新 更多