J'ai la trame de données suivante
x <- read.table(text = " id1 id2 val1 val2
1 a x 1 9
2 a x 2 4
3 a y 3 5
4 a y 4 9
5 b x 1 7
6 b y 4 4
7 b x 3 9
8 b y 2 8", header = TRUE)
Je veux calculer la moyenne de val1 et val2 regroupées par id1 et id2, et compter simultanément le nombre de lignes pour chaque combinaison id1-id2. Je peux effectuer chaque calcul séparément:
# calculate mean
aggregate(. ~ id1 + id2, data = x, FUN = mean)
# count rows
aggregate(. ~ id1 + id2, data = x, FUN = length)
Afin de faire les deux calculs en un seul appel, j'ai essayé
do.call("rbind", aggregate(. ~ id1 + id2, data = x, FUN = function(x) data.frame(m = mean(x), n = length(x))))
Cependant, j'obtiens une sortie déformée avec un avertissement:
# m n
# id1 1 2
# id2 1 1
# 1.5 2
# 2 2
# 3.5 2
# 3 2
# 6.5 2
# 8 2
# 7 2
# 6 2
# Warning message:
# In rbind(id1 = c(1L, 2L, 1L, 2L), id2 = c(1L, 1L, 2L, 2L), val1 = list( :
# number of columns of result is not a multiple of vector length (arg 1)
Je pourrais utiliser le package plyr, mais mon jeu de données est assez volumineux et plyr est très lent (presque inutilisable) lorsque la taille du jeu de données augmente.
Comment puis-je utiliser aggregate
ou d'autres fonctions pour effectuer plusieurs calculs en un seul appel?
aggregate
mentionné dans les réponses, il y a aussiby
ettapply
.Réponses:
Vous pouvez tout faire en une seule étape et obtenir un étiquetage approprié:
Cela crée un dataframe avec deux colonnes id et deux colonnes matricielles:
Comme indiqué par @ lord.garbage ci-dessous, cela peut être converti en un dataframe avec des colonnes "simples" en utilisant
do.call(data.frame, ...)
Voici la syntaxe de plusieurs variables sur le LHS:
la source
d$val1[ , ""mn"]
regarder la structure avecstr
.agg <- aggregate(cbind(val1, val2) ~ id1 + id2, data = x, FUN = function(x) c(mn = mean(x), n = length(x)))
en utilisantagg_df <- do.call(data.frame, agg)
. Voir aussi ici .Compte tenu de cela dans la question:
Ensuite, dans
data.table
(1.9.4+
), vous pouvez essayer:Pour comparer les temps
aggregate
(utilisés dans la question et les 3 autres réponses) pourdata.table
voir ce repère (les casagg
etagg.x
).la source
Vous pouvez ajouter une
count
colonne, agréger avecsum
, puis réduire pour obtenir lemean
:Il a l'avantage de préserver vos noms de colonnes et de créer une seule
count
colonne.la source
En utilisant le
dplyr
package, vous pouvez y parvenir en utilisantsummarise_all
. Avec cette fonction de synthèse, vous pouvez appliquer d'autres fonctions (dans ce casmean
etn()
) à chacune des colonnes non groupées:qui donne:
Si vous ne voulez pas appliquer la (les) fonction (s) à toutes les colonnes non groupées, vous spécifiez les colonnes auxquelles elles doivent être appliquées ou en excluant les non-voulues avec un moins en utilisant la
summarise_at()
fonction:la source
Vous souhaitez peut-être fusionner ?
la source
Vous pouvez également utiliser
plyr::each()
pour introduire plusieurs fonctions:la source
Une autre
dplyr
option est celleacross
qui fait partie de la version de développement actuelleRésultat
la source