Wie gruppieren / standardisieren Sie Variablen in R?

9

Zu den mir vertrauten Funktionen gehören Skalierung von Basis R und Neuskalierung von ARM.

Vielleicht wäre der beste Weg, eine Variante von apply zu verwenden und eine oder mehrere Variablen anzugeben, die als Gruppierungsvariablen verwendet werden sollen.

Michael Bishop
quelle
Versuchen Sie: Aggregat (state.x77, Liste (Region = state.region, Cold = state.x77 [, "Frost"]> 130)), Funktion (x) ((x - Mittelwert (x)) / sd (x) ))
Suncoolsu

Antworten:

7

Hier ist eine mögliche Plyr- Lösung. Beachten Sie, dass es auf der transform()Basisfunktion beruht .

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

(Wir können überprüfen , ob es sich wie bei zB erwartet funktioniert, with(subset(my.df, sex=="F" & group=="A"), scale(x)))

Grundsätzlich beschreibt das 2. Argument, wie die Daten "aufgeteilt" werden, das 3. Argument, welche Funktion auf jeden Block angewendet werden soll. Mit dem obigen x.stdBefehl wird eine Variable an den data.frame angehängt. Verwenden xSie diese Option, wenn Sie Ihre ursprüngliche Variable durch die skalierte ersetzen möchten.

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

Hier ist eine data.table- Lösung. Es ist definitiv schneller als Plyr (nur für große Datenmengen relevant). Vielleicht mache ich später ein Dplyr-Beispiel.

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

(Ja, ich habe eine Frage wiederentdeckt, die ich vor Jahren gestellt habe, als ich ein R-Noob war.)

Michael Bishop
quelle
2

Sie können dies (unter anderem) verwenden tapply(das plyrPaket enthält viele andere Optionen, die für Ihre spezielle Situation möglicherweise besser geeignet sind):

tapply(variabletoscale, list(groupvar1, groupvar2), scale)
Nick Sabbe
quelle
1
Mit zwei Faktoren wird kein data.frame zurückgegeben. Sie müssen das Ergebnis dafür nachbearbeiten.
Chl
0

Diese Antwort stammt aus einem Whitepaper von Mahmood Arai. Es hat den bequemen Nebeneffekt, die zentrierten Ergebnisse mit dem Präfix "C" zu kennzeichnen:

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
quelle
0

Hier ist eine aktualisierte Implementierung mit dplyr von 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
quelle