4
votes

R rangé signifie d'un sous-ensemble de colonnes

Je voudrais calculer des variables récapitulatives à partir de plusieurs colonnes dans un bloc de données. Ceci est possible lors de la saisie de tous les noms de lignes, mais je voudrais utiliser starts_with () et des fonctions similaires. Ie

df %>% mutate(A = mean(A1:A3))
df %>% group_by(row_number()) %>% mutate(A = mean(A1:A3))
df %>% group_by(row_number()) %>% mutate(A = mean(starts_with("A")))

Ce qui fonctionne:

library(tidyverse)
df %>% mutate(A = (A1 + A2 + A3)/3)
df %>% mutate(A = rowMeans(select(., A1:A3)))

Cependant, le premier devient ennuyeux lors de la synthèse de nombreuses variables, tandis que le second devient incroyablement lent très rapidement lorsque résumant de nombreuses lignes. Je soupçonne qu'il doit y avoir une solution plus rapide.

Ce qui ne fonctionne pas:

df <- data.frame(A1 = rnorm(100, 0, 1),
                 A2 = rnorm(100, 0, 1),
                 A3 = rnorm(100, 0, 1),
                 B1 = rnorm(100, 0, 1),
                 B2 = rnorm(100, 0, 1))

Ma question est donc la suivante: y a-t-il un moyen d'utiliser mean () etc. dans mutate () pour calculer les moyennes de lignes, idéalement sans avoir à épeler chaque variable?


0 commentaires

3 Réponses :


5
votes

Utilisez dans votre fonction select la fonction starts_with:

df %>% mutate(A = rowMeans(select(., starts_with("A"))))

Si vous recherchez l'aide de select_helpers code > vous en trouvez plusieurs autres.


2 commentaires

Merci pour cette réponse. Ceci est essentiellement mon deuxième exemple de «ce qui fonctionne», sauf en utilisant starts_with (). Malheureusement, cela devient très lent très rapidement, alors j'espérais qu'il y aurait une solution plus rapide.


Désolé, j'ai raté la partie performance!



2
votes

Dans ma version précédente, je pensais que rowMeans était le problème, mais en fait, ce qui ralentit le calcul est l'utilisation de select - mieux vaut simplement s'en tenir au famille grep :

df %>% mutate(A = rowMeans(.[, grepl("^A", names(.))]))


0 commentaires

4
votes

Base R est le plus rapide de mes tests.
J'utiliserai une trame de données plus grande.

library(tidyverse)
library(microbenchmark)
library(ggplot2)

set.seed(1234)

n <- 1e4
df <- data.frame(A1 = rnorm(n, 0, 1),
                 A2 = rnorm(n, 0, 1),
                 A3 = rnorm(n, 0, 1),
                 B1 = rnorm(n, 0, 1),
                 B2 = rnorm(n, 0, 1))

mb <- microbenchmark(
  m1 = df %>% mutate(A = (A1 + A2 + A3)/3),
  m2 = df %>% mutate(A = rowMeans(select(., A1:A3))),
  m3 = df %>% mutate(A = reduce(.[, grepl("^A", names(.))], `+`) / ncol(.[, grepl("^A", names(.))])),
  m4 = rowMeans(df[, grep("^A", names(df))]),
  m5 = df[, grep("^A", names(df))] %>% rowMeans()
)

mb

autoplot(mb)

La méthode R purement de base est plus rapide, suivie par le sous-ensemble R de base / dplyr .

p >


2 commentaires

Belle référence! N'affecte pas beaucoup les performances, mais il convient de noter que pour la même sortie, %>% cbind (df, A =.) (ou quelque chose de similaire) devrait être ajouté à m4 et m5 .


@ arg0naut Ou %>% bind_cols (df, A =.) , pour utiliser une fonction dplyr .