Comment regrouper / standardiser des variables dans R?

9

Les fonctions que je connais incluent l' échelle à partir de la base R, la mise à l' échelle à partir d'ARM.

La meilleure façon serait peut-être d'utiliser une variante d'application, en spécifiant une ou plusieurs variables à utiliser comme variables de regroupement.

Michael Bishop
la source
Essayez: agrégat (state.x77, list (Region = state.region, Cold = state.x77 [, "Frost"]> 130)), function (x) ((x - mean (x)) / sd (x) ))
suncoolsu

Réponses:

7

Voici une solution plyr possible . Notez qu'il repose sur la transform()fonction de base .

my.df <- data.frame(x=rnorm(100, mean=10), 
                    sex=sample(c("M","F"), 100, rep=T), 
                    group=gl(5, 20, labels=LETTERS[1:5]))
library(plyr)
ddply(my.df, c("sex", "group"), transform, x.std = scale(x))

(Nous pouvons vérifier si cela fonctionne comme prévu avec par exemple, with(subset(my.df, sex=="F" & group=="A"), scale(x)))

Fondamentalement, le 2ème argument décrit comment "diviser" les données, le 3ème argument quelle fonction appliquer à chaque bloc. Ce qui précède ajoutera une variable x.stdau data.frame. À utiliser xsi vous souhaitez remplacer votre variable d'origine par la variable mise à l'échelle.

chl
la source
7
group.center <- function(var,grp) {
    return(var-tapply(var,grp,mean,na.rm=T)[grp])
}
Thanassi
la source
3

Voici une solution data.table . Il est nettement plus rapide que plyr (pertinent uniquement pour les grands ensembles de données). Peut-être que plus tard je ferai un exemple de dplyr.

# generate example data
raw.data <- data.frame( outcome = c(rnorm(500, 100, 15), rnorm(500, 110, 12)), 
                        group = c(rep("a", 500), rep("b", 500)))

library(data.table)
# convert dataframe to data.table
raw.data <- data.table(raw.data, key = "group")

# create group standardized outcome variable
raw.data[ , group_std_outcome := (outcome - mean(outcome, na.rm = TRUE)) /  
           sd(outcome, na.rm = TRUE), "group"]

(Oui, j'ai redécouvert une question que j'ai posée il y a des années quand j'étais un Noob R;)

Michael Bishop
la source
2

Vous pouvez utiliser (entre autres) tapplypour cela (le plyrpackage contient de nombreuses autres options qui peuvent être mieux adaptées à votre situation spécifique):

tapply(variabletoscale, list(groupvar1, groupvar2), scale)
Nick Sabbe
la source
1
Avec deux facteurs, il ne renverra pas de data.frame. Vous devrez post-traiter le résultat pour cela.
chl
0

Cette réponse est tirée d'un livre blanc de Mahmood Arai. Il a pour effet secondaire de marquer les résultats centrés avec le préfixe "C.":

gcenter <- function(df1,group) {
        variables <- paste(
              rep("C", ncol(df1)),  colnames(df1), sep=".")
        copydf <- df1
        for (i in 1:ncol(df1)) {
              copydf[,i] <- df1[,i] - ave(df1[,i], group, FUN=mean)}
        colnames(copydf) <- variables
        return(cbind(df1,copydf))}
RegressForward
la source
0

Voici une implémentation mise à jour utilisant dplyr de tidyverse .

library(tidyverse)

my.df <- data.frame(x=rnorm(100, mean=10), sex=sample(c("M","F"), 100, rep=T))
my.df <- group_by(my.df, sex) %>% mutate(x.sd = as.numeric(scale(x)))
Brian Levey
la source