Alors disons que j'ai un vecteur

a <- rnorm(6000)

Je veux calculer la moyenne de la 1ère valeur à la 60e, puis à nouveau calculer la moyenne de la 61e valeur à la 120e et donc à la quatrième. Donc, fondamentalement, je veux calculer la moyenne pour toutes les 60 valeurs en me donnant 100 moyennes à partir de ce vecteur. Je sais que je peux faire une boucle for mais j'aimerais savoir s'il existe une meilleure façon de le faire

5
arezaie 26 avril 2017 à 16:36

3 réponses

Meilleure réponse

J'utiliserais

 colMeans(matrix(a, 60))
.colMeans(a, 60, length(a) / 60)  # more efficient (without reshaping to matrix)

Amélioration à la demande de l'utilisateur adunaic

Cela ne fonctionne que s'il y a 60x100 points de données. Si vous avez un 60 incomplet à la fin, ces erreurs. Il serait bon d'avoir une solution générale pour les autres qui cherchent des idées sur ce problème.

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

Solution alternative avec opération groupée (moins efficace)

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

Vitesse

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
13
李哲源 23 sept. 2018 à 17:09

Une autre option consiste à utiliser tapply en créant une variable de regroupement.

La variable de regroupement peut être créée de deux manières:

1) Utilisation de rep

tapply(a, rep(seq_along(a), each = n, length.out = length(a)), mean)

2) Utilisation de gl

tapply(a, gl(length(a)/n, n), mean)

Si nous convertissons le vecteur en dataframe / tibble, nous pouvons utiliser la même logique et calculer le mean

aggregate(a~gl(length(a)/n, n), data.frame(a), mean)

OU avec dplyr

library(dplyr)

tibble::tibble(a) %>%
          group_by(group = gl(length(a)/n, n)) %>%
          summarise(mean_val = mean(a))

données

set.seed(1234)
a <- rnorm(6000)
n <- 60
1
Ronak Shah 22 avril 2019 à 02:01

Je recommanderais d'utiliser la fonction sapply:

a <- rnorm(6000)
seq <- seq(1, length(a), 60)
a_mean <- sapply(seq, function(i) {mean(a[i:(i+59)])})
1
Daniel Freeman 23 juil. 2019 à 15:46