it-swarm.com.de

Datenspalten in R standardisieren

Ich habe ein Dataset namens spam, das 58 Spalten und ungefähr 3500 Datenzeilen enthält, die sich auf Spam-Nachrichten beziehen. 

Ich habe vor, in Zukunft eine lineare Regression für dieses Dataset auszuführen, aber ich möchte im Vorfeld einige Vorverarbeitungen durchführen und die Spalten so standardisieren, dass sie den Mittelwert und die Einheitsvarianz von null haben. 

Mir wurde gesagt, der beste Weg, dies zu tun, ist mit R, also möchte ich fragen wie kann ich mit R eine Normalisierung erreichen? Ich habe die Daten bereits richtig geladen und suche nur nach Paketen oder Methoden, um diese Aufgabe auszuführen. 

150
Hoser

Ich muss davon ausgehen, dass Sie sagen wollten, dass Sie einen Mittelwert von 0 und eine Standardabweichung von 1 wollten. Wenn sich Ihre Daten in einem Datenrahmen befinden und alle Spalten numerisch sind, können Sie einfach die Funktion scale der Daten aufrufen, um das zu tun, was Sie möchten .

dat <- data.frame(x = rnorm(10, 30, .2), y = runif(10, 3, 5))
scaled.dat <- scale(dat)

# check that we get mean of 0 and sd of 1
colMeans(scaled.dat)  # faster version of apply(scaled.dat, 2, mean)
apply(scaled.dat, 2, sd)

Die Verwendung von eingebauten Funktionen ist klasse. Wie diese Katze:

enter image description here

428
Dason

Da mir klar wird, dass die Frage alt ist und eine Antwort akzeptiert wird, werde ich eine andere Antwort geben.

scale ist durch die Tatsache begrenzt, dass alle Variablen skaliert werden. Mit der folgenden Lösung können nur bestimmte Variablennamen skaliert werden, während andere Variablen unverändert bleiben (und die Variablennamen könnten dynamisch generiert werden):

library(dplyr)

set.seed(1234)
dat <- data.frame(x = rnorm(10, 30, .2), 
                  y = runif(10, 3, 5),
                  z = runif(10, 10, 20))
dat

dat2 <- dat %>% mutate_each_(funs(scale(.) %>% as.vector), 
                             vars=c("y","z"))
dat2

was mir das gibt:

> dat
          x        y        z
1  29.75859 3.633225 14.56091
2  30.05549 3.605387 12.65187
3  30.21689 3.318092 13.04672
4  29.53086 3.079992 15.07307
5  30.08582 3.437599 11.81096
6  30.10121 4.621197 17.59671
7  29.88505 4.051395 12.01248
8  29.89067 4.829316 12.58810
9  29.88711 4.662690 19.92150
10 29.82199 3.091541 18.07352

und 

> dat2 <- dat %>% mutate_each_(funs(scale(.) %>% as.vector), 
>                              vars=c("y","z"))
> dat2
          x          y           z
1  29.75859 -0.3004815 -0.06016029
2  30.05549 -0.3423437 -0.72529604
3  30.21689 -0.7743696 -0.58772361
4  29.53086 -1.1324181  0.11828039
5  30.08582 -0.5946582 -1.01827752
6  30.10121  1.1852038  0.99754666
7  29.88505  0.3283513 -0.94806607
8  29.89067  1.4981677 -0.74751378
9  29.88711  1.2475998  1.80753470
10 29.82199 -1.1150515  1.16367556

EDIT: Angesprochener Kommentar von Julian: Die Ausgabe von scale ist eine Nx1-Matrix. Idealerweise sollten Sie einen as.vector hinzufügen, um den Matrixtyp zurück in einen Vektortyp zu konvertieren. Danke Julian!

64
akhmed

Das ist 3 Jahre alt. Dennoch muss ich Folgendes hinzufügen:

Die häufigste Normalisierung ist die z-Transformation , bei der Sie den Mittelwert abziehen und durch die Standardabweichung Ihrer Variablen dividieren. Das Ergebnis wird mean = 0 und sd = 1 haben.

Dafür brauchen Sie kein Paket.

zVar <- (myVar - mean(myVar)) / sd(myVar)

Das ist es.

49
fmb

Das Caret-Paket bietet Methoden für die Vorverarbeitung von Daten (z. B. Zentrieren und Skalieren). Sie können auch den folgenden Code verwenden:

library(caret)
# Assuming goal class is column 10
preObj <- preProcess(data[, -10], method=c("center", "scale"))
newData <- predict(preObj, data[, -10])

Weitere Details: http://www.inside-r.org/node/86978

18
DaniM

Als ich die von Dason angegebene Lösung verwendete, erhielt ich anstelle eines Datenrahmens einen Vektor mit Zahlen (die skalierten Werte meines df).

Falls jemand das gleiche Problem hat, müssen Sie dem Code as.data.frame () hinzufügen:

df.scaled <- as.data.frame(scale(df))

Ich hoffe, das ist nützlich für Leute, die das gleiche Problem haben!

12
Diego

Sie können die Daten auch mit Hilfe der data.Normalization-Funktion im clusterSim-Paket problemlos normalisieren. Es bietet eine andere Methode zur Datennormalisierung.

    data.Normalization (x,type="n0",normalization="column")

Argumente

x
Vektor, Matrix oder Datensatz Typ
Art der Normalisierung: n0 - ohne Normalisierung

n1 - Standardisierung ((x-Mittelwert)/sd)

n2 - Positionsstandardisierung ((x-Median)/mad)

n3 - Einheit ((x-Mittelwert)/Bereich)

n3a - positionelle Einheit ((x-Median)/Bereich)

n4 - Einheit mit Nullminimum ((x-min)/Bereich)

n5 - Normalisierung im Bereich <-1,1> ((x-Mittelwert)/max (abs (x-Mittelwert)))

n5a - Positionsnormalisierung im Bereich <-1,1> ((x-Median)/max (abs (X-Median)))

n6 - Quotiententransformation (x/sd)

n6a - Positionsquotiententransformation (x/mad)

n7 - Quotiententransformation (x/Bereich)

n8 - Quotiententransformation (x/max)

n9 - Quotiententransformation (x/Mittelwert)

n9a - Positionsquotiententransformation (x/Median)

n10 - Quotiententransformation (x/Summe)

n11 - Quotiententransformation (x/sqrt (SSQ))

n12 - Normalisierung ((x-Mittelwert)/sqrt (Summe ((x-Mittelwert) ^ 2)))

n12a - Positionsnormalisierung ((x-Median)/sqrt (Summe ((x-Median) ^ 2)))

n13 - Normalisierung mit Null als Mittelpunkt ((x-Mittelbereich)/(Bereich/2))

normalisierung
"column" - Normalisierung nach Variable, "Zeile" - Normalisierung nach Objekt

11
Samehmagd

Auch wenn dies eine alte Frage ist, ist sie sehr relevant! Und ich habe einen einfachen Weg gefunden, bestimmte Spalten zu normalisieren, ohne Pakete zu benötigen:

normFunc <- function(x){(x-mean(x, na.rm = T))/sd(x, na.rm = T)}

Zum Beispiel

x<-rnorm(10,14,2)
y<-rnorm(10,7,3)
z<-rnorm(10,18,5)
df<-data.frame(x,y,z)

df[2:3] <- apply(df[2:3], 2, normFunc)

Sie werden sehen, dass die y- und z-Spalten normalisiert wurden. Keine Pakete benötigt :-)

5
BBKim

Mit dplyr v0.7.4 können alle Variablen mit mutate_all() skaliert werden:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tibble)

set.seed(1234)
dat <- tibble(x = rnorm(10, 30, .2), 
              y = runif(10, 3, 5),
              z = runif(10, 10, 20))

dat %>% mutate_all(scale)
#> # A tibble: 10 x 3
#>         x      y       z
#>     <dbl>  <dbl>   <dbl>
#>  1 -0.827 -0.300 -0.0602
#>  2  0.663 -0.342 -0.725 
#>  3  1.47  -0.774 -0.588 
#>  4 -1.97  -1.13   0.118 
#>  5  0.816 -0.595 -1.02  
#>  6  0.893  1.19   0.998 
#>  7 -0.192  0.328 -0.948 
#>  8 -0.164  1.50  -0.748 
#>  9 -0.182  1.25   1.81  
#> 10 -0.509 -1.12   1.16

Bestimmte Variablen können mit mutate_at() ausgeschlossen werden:

dat %>% mutate_at(scale, .vars = vars(-x))
#> # A tibble: 10 x 3
#>        x      y       z
#>    <dbl>  <dbl>   <dbl>
#>  1  29.8 -0.300 -0.0602
#>  2  30.1 -0.342 -0.725 
#>  3  30.2 -0.774 -0.588 
#>  4  29.5 -1.13   0.118 
#>  5  30.1 -0.595 -1.02  
#>  6  30.1  1.19   0.998 
#>  7  29.9  0.328 -0.948 
#>  8  29.9  1.50  -0.748 
#>  9  29.9  1.25   1.81  
#> 10  29.8 -1.12   1.16

Erstellt am 24.08.2014 durch das Paket reprex (v0.2.0).

4
pat-s

Die Skalierung kann sowohl für den vollständigen Datenrahmen als auch für bestimmte Spalten verwendet werden.

trainingSet[, 3:7] = scale(trainingSet[, 3:7]) # For column 3 to 7
trainingSet[, 8] = scale(trainingSet[, 8]) # For column 8 

Voller Datenrahmen

trainingSet <- scale(trainingSet)
2
Amit

Bevor ich diesen Thread fand, hatte ich das gleiche Problem. Ich hatte benutzerabhängige Spaltentypen, also schrieb ich eine for-Schleife, die durch sie ging und benötigte Spalten scale 'erhielt. D. Es gibt wahrscheinlich bessere Möglichkeiten, dies zu tun, aber das Problem wurde dadurch gelöst:

 for(i in 1:length(colnames(df))) {
        if(class(df[,i]) == "numeric" || class(df[,i]) == "integer") {
            df[,i] <- as.vector(scale(df[,i])) }
        }

as.vector ist ein notwendiger Teil, da sich herausstellte, dass scalerownames x 1-Matrix ist, was normalerweise nicht das ist, was Sie in Ihrem data.frame haben möchten.

1
Claud H

Verwenden Sie das Paket "recommenderlab". Laden Sie das Paket herunter und installieren Sie es ... .. Dieses Paket enthält den Befehl "Normalisieren". Sie können auch eine der vielen Methoden zur Normalisierung auswählen, nämlich 'center' oder 'Z-score' Folgen Sie dem folgenden Beispiel:

## create a matrix with ratings
m <- matrix(sample(c(NA,0:5),50, replace=TRUE, prob=c(.5,rep(.5/6,6))),nrow=5, ncol=10, dimnames = list(users=paste('u', 1:5, sep=&rdquo;), items=paste('i', 1:10, sep=&rdquo;)))

## do normalization
r <- as(m, "realRatingMatrix")
#here, 'centre' is the default method
r_n1 <- normalize(r) 
#here "Z-score" is the used method used
r_n2 <- normalize(r, method="Z-score")

r
r_n1
r_n2

## show normalized data
image(r, main="Raw Data")
image(r_n1, main="Centered")
image(r_n2, main="Z-Score Normalization")
0
user3601993

Das Paket dplyr verfügt über zwei Funktionen, die dies tun.

> require(dplyr)

Um spezifische -Spalten einer Datentabelle zu mutieren, können Sie die Funktion mutate_at() verwenden. Um alle -Spalten zu mutieren, können Sie mutate_all verwenden.

Im Folgenden finden Sie ein kurzes Beispiel für die Verwendung dieser Funktionen zur Standardisierung von Daten.

Bestimmte Spalten mutieren:

dt = data.table(a = runif(3500), b = runif(3500), c = runif(3500))
dt = data.table(dt %>% mutate_at(vars("a", "c"), scale)) # can also index columns by number, e.g., vars(c(1,3))

> apply(dt, 2, mean)
            a             b             c 
 1.783137e-16  5.064855e-01 -5.245395e-17 

> apply(dt, 2, sd)
        a         b         c 
1.0000000 0.2906622 1.0000000 

Mutiere alle Spalten:

dt = data.table(a = runif(3500), b = runif(3500), c = runif(3500))
dt = data.table(dt %>% mutate_all(scale))

> apply(dt, 2, mean)
            a             b             c 
-1.728266e-16  9.291994e-17  1.683551e-16 

> apply(dt, 2, sd)
a b c 
1 1 1 
0
Jack