web-dev-qa-db-fra.com

Colonnes de nom dans l'agrégat en R

Je sais que je peux * re * nommer les colonnes après avoir agrégé les données:

blubb <- aggregate(dat$two ~ dat$one, ...)
colnames(blubb) <- c("One", "Two")

Aucun problème avec ça. Mais existe-t-il un moyen d'agréger et de nommer les colonnes en une seule fois? Un peu comme:

blubb <- aggregate( ... , cols = c("One", "Two"))

Il serait particulièrement agréable (et à l'épreuve des fautes de frappe) d'attraper en quelque sorte les noms de colonnes d'origine et de faire comme:

blubb <- aggregate( ... , cols = c(name_of_dat$one, name_of_dat$two."_Mean"))
51
user1322720

Vous pouvez utiliser setNames comme dans:

blubb <- setNames(aggregate(dat$two ~ dat$one, ...), c("One", "Two"))

Alternativement, vous pouvez contourner la méthode de la formule lisse et utiliser une syntaxe comme:

blubb <- aggregate(list(One = dat$one), list(Two = dat$two), ...)

Mise à jour

Cette mise à jour est juste pour vous aider à démarrer vous-même la dérivation d'une solution.

Si vous inspectez le code pour stats:::aggregate.formula, Vous verrez les lignes suivantes vers la fin:

if (is.matrix(mf[[1L]])) {
    lhs <- as.data.frame(mf[[1L]])
    names(lhs) <- as.character(m[[2L]][[2L]])[-1L]
    aggregate.data.frame(lhs, mf[-1L], FUN = FUN, ...)
}
else aggregate.data.frame(mf[1L], mf[-1L], FUN = FUN, ...)

Si tout ce que vous voulez faire est d'ajouter le nom de la fonction à la variable qui a été agrégée, vous pouvez peut-être changer cela en quelque chose comme:

if (is.matrix(mf[[1L]])) {
  lhs <- as.data.frame(mf[[1L]])
  names(lhs) <- as.character(m[[2L]][[2L]])[-1L]
  myOut <- aggregate.data.frame(lhs, mf[-1L], FUN = FUN, ...)
  colnames(myOut) <- c(names(mf[-1L]), 
                       paste(names(lhs), deparse(substitute(FUN)), sep = "."))
}
else {
  myOut <- aggregate.data.frame(mf[1L], mf[-1L], FUN = FUN, ...)
  colnames(myOut) <- c(names(mf[-1L]), 
                       paste(strsplit(gsub("cbind\\(|\\)|\\s", "", 
                                           names(mf[1L])), ",")[[1]],
                             deparse(substitute(FUN)), sep = "."))
} 
myOut

Cela capture essentiellement la valeur entrée pour FUN en utilisant deparse(substitute(FUN)), vous pouvez donc probablement modifier la fonction pour accepter un suffixe personnalisé, ou peut-être même un vecteur de suffixes. Cela peut probablement être amélioré un peu avec du travail, mais je ne vais pas le faire!

Voici n Gist avec ce concept appliqué, créant une fonction nommée "myAgg".

Voici un exemple de sortie uniquement des noms de colonne résultants :

> names(myAgg(weight ~ feed, data = chickwts, mean))
[1] "feed"        "weight.mean"
> names(myAgg(breaks ~ wool + tension, data = warpbreaks, sum))
[1] "wool"       "tension"    "breaks.sum"
> names(myAgg(weight ~ feed, data = chickwts, FUN = function(x) mean(x^2)))
[1] "feed"                         "weight.function(x) mean(x^2)"

Notez que seul le nom de variable agrégée change. Mais notez également que si vous utilisez une fonction personnalisée, vous vous retrouverez avec un nom de colonne vraiment étrange!

67

La réponse à votre première question est oui. Vous pouvez certainement inclure les noms de colonne dans la fonction d'agrégation. En utilisant les noms de votre exemple ci-dessus:

blubb <- aggregate(dat,list(One=dat$One,Two=dat$Two),sum)

J'aime la partie sur l'extraction éventuelle des noms de colonnes d'origine automatiquement. Si je le découvre, je le posterai.

9
orville jackson

Si vous préférez écrire des agrégats sous la forme formula, la documentation montre l'utilisation de cbind. Et cbind vous permet de nommer ses arguments, qui sont utilisés par aggregate.

blubb <- aggregate(cbind(Two = dat$two) ~ cbind(One = dat$one), ...)

L'agrégation de plus d'une colonne par plus d'un facteur de regroupement pourrait se faire comme:

blubb <- aggregate(cbind(x = varX, y = varY, varZ) ~ cbind(a = facA) + cbind(b = facB) + facC, data=dat, FUN=sum)

et si vous souhaitez utiliser plusieurs fonctions:

aggregate(cbind(cases=ncases, ncontrols) ~ cbind(alc=alcgp) + tobgp, data = esoph, FUN = function(x) c("mean" = mean(x), "median" = median(x)))

#   alc    tobgp cases.mean cases.median ncontrols.mean ncontrols.median
#1    1 0-9g/day  1.5000000    1.0000000      43.500000        47.000000
#2    2 0-9g/day  5.6666667    4.0000000      29.833333        34.500000
#...

ce qui ajoute au nom de colonne la fonction d'agrégation utilisée.

Mais cbind remplace factors par leurs codes internes. Pour éviter cela, vous pouvez utiliser:

with(esoph, aggregate(data.frame(cases=ncases, ncontrols), data.frame(alc=alcgp, tobgp), FUN = function(x) c("mean" = mean(x), "median" = median(x))))

#         alc    tobgp cases.mean cases.median ncontrols.mean ncontrols.median
#1  0-39g/day 0-9g/day  1.5000000    1.0000000      43.500000        47.000000
#2      40-79 0-9g/day  5.6666667    4.0000000      29.833333        34.500000
#...
0
GKi