Jak grupować / standaryzować zmienne w R?

9

Znane mi funkcje obejmują skalowanie od podstawy R, przeskalowanie od ARM.

Być może najlepszym sposobem byłoby użycie jakiegoś wariantu zastosowania, określając jedną lub więcej zmiennych do zastosowania jako zmienne grupujące.

Michael Bishop
źródło
Wypróbuj: agreguj (stan.x77, lista (Region = region.region, Zimno = stan.x77 [, „Frost”]> 130)), funkcja (x) ((x - średnia (x)) / sd (x) ))
suncoolsu,

Odpowiedzi:

7

Oto możliwe plyr rozwiązanie. Zauważ, że opiera się on na transform()funkcji podstawowej .

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))

(Możemy sprawdzić, czy działa zgodnie z oczekiwaniami, np. with(subset(my.df, sex=="F" & group=="A"), scale(x)))

Zasadniczo drugi argument opisuje, jak „podzielić” dane, trzeci argument to, jaką funkcję zastosować do każdej porcji. Powyższe spowoduje dołączenie zmiennej x.stddo data.frame. Użyj, xjeśli chcesz zastąpić oryginalną zmienną skalowaną.

chl
źródło
7
group.center <- function(var,grp) {
    return(var-tapply(var,grp,mean,na.rm=T)[grp])
}
Thanassi
źródło
3

Oto rozwiązanie data.table . Jest zdecydowanie szybszy niż plyr (dotyczy tylko dużych zestawów danych). Może później zrobię lepszy przykład.

# 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"]

(Tak, odkryłem pytanie, które zadałem lata temu, kiedy byłem R noobem;)

Michael Bishop
źródło
2

Możesz do tego użyć (między innymi) tapply( plyrpakiet zawiera wiele innych opcji, które mogą być lepiej dostosowane do konkretnej sytuacji):

tapply(variabletoscale, list(groupvar1, groupvar2), scale)
Nick Sabbe
źródło
1
Z dwoma czynnikami nie zwróci ramki danych. W tym celu musisz przetworzyć wynik.
chl
0

Ta odpowiedź pochodzi z białej księgi Mahmood Arai. Ma wygodny efekt uboczny, oznaczając wyśrodkowane wyniki przedrostkiem „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))}
Regress Forward
źródło
0

Oto zaktualizowana implementacja wykorzystująca dplyr z 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
źródło