Como agrupar / centralizar variáveis ​​em R?

9

As funções que eu estou familiarizado incluem a escala da base R, a nova escala do ARM.

Talvez a melhor maneira seja usar alguma variante de apply, especificando uma ou mais variáveis ​​para usar como variáveis ​​de agrupamento.

Michael Bishop
fonte
Tente: agregado (estado.x77, lista (Região = estado.região, Frio = estado.x77 [, "Frost"]> 130)), função (x) ((x - média (x)) / sd (x) ))
suncoolsu 8/09/11

Respostas:

7

Aqui está uma possível solução plyr . Observe que ele depende da transform()função 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))

(Podemos verificar se funciona como esperado com, por exemplo, with(subset(my.df, sex=="F" & group=="A"), scale(x)))

Basicamente, o segundo argumento descreve como "dividir" os dados; o terceiro argumento, que função aplicar a cada pedaço. O acima irá anexar uma variável x.stdao data.frame. Use xse você deseja substituir sua variável original pela variável em escala.

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

Aqui está uma solução data.table . É definitivamente mais rápido que plyr (relevante apenas para grandes conjuntos de dados). Talvez mais tarde eu faça um exemplo 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"]

(Sim, redescobri uma pergunta que fiz anos atrás, quando eu era R noob;)

Michael Bishop
fonte
2

Você pode usar (entre outros) tapplypara isso (o plyrpacote contém muitas outras opções que podem ser mais adequadas para sua situação específica):

tapply(variabletoscale, list(groupvar1, groupvar2), scale)
Nick Sabbe
fonte
11
Com dois fatores, ele não retornará um data.frame. Você precisará pós-processar o resultado para isso.
chl
0

Esta resposta é de um white paper de Mahmood Arai. Tem o efeito colateral conveniente de rotular os resultados centralizados com o prefixo "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
fonte
0

Aqui está uma implementação atualizada usando o dplyr do 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
fonte