Standaard gegevenskolommen in R

Ik heb een dataset met de naam spamdie 58 kolommen en ongeveer 3500 rijen met gegevens met betrekking tot spamberichten bevat.

Ik ben van plan om in de toekomst wat lineaire regressie uit te voeren op deze dataset, maar ik zou graag vooraf wat voorverwerking willen doen en de kolommen standaardiseren om een gemiddelde nul- en eenheidsvariantie te hebben.

Er is mij verteld dat ik dit het beste kan doen met R, dus ik zou graag willen vragen hoe kan ik normalisatie bereiken met R? Ik heb de gegevens al correct geladen en ik ben gewoon op zoek naar enkele pakketten of methoden om deze taak uit te voeren.


Antwoord 1, autoriteit 100%

Ik neem aan dat je bedoelde te zeggen dat je een gemiddelde van 0 en een standaarddeviatie van 1 wilde. Als je gegevens in een dataframe staan en alle kolommen numeriek zijn, kun je eenvoudig de scalefunctie op de gegevens om te doen wat je wilt.

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)

Het gebruik van ingebouwde functies is stijlvol. Vind deze kat leuk:


Antwoord 2, autoriteit 18%

Als ik me realiseer dat de vraag oud is en één antwoord is geaccepteerd, geef ik een ander antwoord ter referentie.

scalewordt beperkt door het feit dat het alle variabelenschaalt. Met de onderstaande oplossing kunnen alleen specifieke variabelenamen worden geschaald terwijl andere variabelen ongewijzigd blijven (en de variabelenamen kunnen dynamisch worden gegenereerd):

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_at(c("y", "z"), ~(scale(.) %>% as.vector))
dat2

wat me dit geeft:

> 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

en

> dat2 <- dat %>% mutate_at(c("y", "z"), ~(scale(.) %>% as.vector))
> 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 1 (2016): Reactie van Julian beantwoord: de uitvoer van scaleis Nx1-matrix, dus idealiter zouden we een as.vectormoeten toevoegen om het matrixtype weer om te zetten in een vectortype. Bedankt Julian!

EDIT 2 (2019): De opmerking van Duccio A. citeren: Voor de nieuwste dplyr (versie 0.8) moet je dplyr::funcs wijzigen met een lijst, zoals dat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))

EDIT 3 (2020): Met dank aan @mj_whales: de oude oplossing is verouderd en nu moeten we mutate_atgebruiken.


Antwoord 3, autoriteit 12%

Dit is 3 jaar oud. Toch heb ik het gevoel dat ik het volgende moet toevoegen:

De meest voorkomende normalisatie is de z-transformatie, waarbij u het gemiddelde aftrekt en deelt door de standaarddeviatie van uw variabele. Het resultaat is mean=0 en sd=1.

Daarvoor heb je geen pakket nodig.

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

Dat is het.


Antwoord 4, autoriteit 4%

Het ‘Caret’-pakket biedt methoden voor het voorbewerken van gegevens (bijv. centreren en schalen). U kunt ook de volgende code gebruiken:

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

Meer details: http://www.inside-r.org/node/86978


Antwoord 5, autoriteit 3%

Toen ik de oplossing van Dason gebruikte, kreeg ik in plaats van een dataframe als resultaat een vector van getallen (de geschaalde waarden van mijn df).

Als iemand hetzelfde probleem heeft, moet je as.data.frame() als volgt aan de code toevoegen:

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

Ik hoop dat dit nuttig is voor mensen die hetzelfde probleem hebben!


Antwoord 6, autoriteit 3%

U kunt de gegevens ook gemakkelijk normaliseren met de functie data.Normalization in clusterSim-pakket. Het biedt verschillende methoden voor gegevensnormalisatie.

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

Argumenten

x
vector, matrix of dataset
typ
type normalisatie:
n0 – zonder normalisatie

n1 – standaardisatie ((x-mean)/sd)

n2 – positionele standaardisatie ((x-mediaan)/mad)

n3 – unitization ((x-mean)/range)

n3a – positionele eenheidsvorming ((x-mediaan)/bereik)

n4 – unitisatie met nul minimum ((x-min)/bereik)

n5 – normalisatie binnen bereik <-1,1> ((x-mean)/max(abs(x-mean)))

n5a – positionele normalisatie binnen bereik <-1,1> ((x-mediaan)/max(abs(x-mediaan)))

n6 – quotiënttransformatie (x/sd)

n6a – positionele quotiënttransformatie (x/mad)

n7 – quotiënttransformatie (x/bereik)

n8 – quotiënttransformatie (x/max)

n9 – quotiënttransformatie (x/gemiddelde)

n9a – positionele quotiënttransformatie (x/mediaan)

n10 – quotiënttransformatie (x/som)

n11 – quotiënttransformatie (x/sqrt(SSQ))

n12 – normalisatie ((x-mean)/sqrt(sum((x-mean)^2)))

n12a – positionele normalisatie ((x-mediaan)/sqrt(sum((x-mediaan)^2)))

n13 – normalisatie waarbij nul het centrale punt is ((x-midrange)/(range/2))

normalisatie
“column” – normalisatie per variabele, “row” – normalisatie per object


Antwoord 7, autoriteit 3%

Met dplyrv0.7.4 kunnen alle variabelen worden geschaald met mutate_all():

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

Specifieke variabelen kunnen worden uitgesloten met mutate_at():

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

Gemaakt op 24-04-2018 door het reprex-pakket(v0.2.0).


Antwoord 8, autoriteit 2%

Schaal kan worden gebruikt voor zowel volledige dataframes als specifieke kolommen.
Voor specifieke kolommen kan de volgende code worden gebruikt:

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

Volledig gegevensframe

trainingSet <- scale(trainingSet)

Antwoord 9, autoriteit 2%

Nogmaals, ook al is dit een oude vraag, het is zeer relevant! En ik heb een eenvoudige manier gevonden om bepaalde kolommen te normaliseren zonder dat er pakketten nodig zijn:

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

Bijvoorbeeld

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)

Je zult zien dat de kolommen y en z zijn genormaliseerd. Geen pakketten nodig 🙂


Antwoord 10

Het pakket dplyrheeft twee functies die dit doen.

> require(dplyr)

Om specifiekekolommen van een gegevenstabel te muteren, kunt u de functie mutate_at()gebruiken. Om allekolommen te muteren, kun je mutate_allgebruiken.

Het volgende is een kort voorbeeld voor het gebruik van deze functies om gegevens te standaardiseren.

Specifieke kolommen muteren:

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 

Alle kolommen muteren:

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 

Antwoord 11

Voordat ik deze thread toevallig vond, had ik hetzelfde probleem. Ik had gebruikersafhankelijke kolomtypen, dus schreef ik een for-lus die er doorheen ging en de benodigde kolommen kreeg die scale‘d. Er zijn waarschijnlijk betere manieren om het te doen, maar dit loste het probleem prima op:

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

as.vectoris een noodzakelijk onderdeel, omdat bleek dat scalerownames x 1matrix doet, wat meestal niet is wat je wilt hebben in uw data.frame.


Antwoord 12

@BBKim gaf vrijwel het beste antwoord, maar het kan ook korter. Het verbaast me dat nog niemand het heeft bedacht.


dat <- data.frame(x = rnorm(10, 30, .2), y = runif(10, 3, 5))
dat <- apply(dat, 2, function(x) (x - mean(x)) / sd(x))


Antwoord 13

Het collapsepakket biedt de snelste schaalfunctie – geïmplementeerd in C++ met behulp van Welfords Online Algorithm:

dat <- data.frame(x = rnorm(1e6, 30, .2), 
                  y = runif(1e6, 3, 5),
                  z = runif(1e6, 10, 20))
library(collapse)
library(microbenchmark)
microbenchmark(fscale(dat), scale(dat))
Unit: milliseconds
        expr       min       lq      mean    median        uq      max neval cld
 fscale(dat)  27.86456  29.5864  38.96896  30.80421  43.79045 313.5729   100  a 
  scale(dat) 357.07130 391.0914 489.93546 416.33626 625.38561 793.2243   100   b

Bovendien: fscaleis S3 generiek voor vectoren, matrices en dataframes en ondersteunt ook gegroepeerde en/of gewogen schaalbewerkingen, evenals schalen naar willekeurige gemiddelden en standaarddeviaties.


Antwoord 14

Gebruik het pakket “recommenderlab”. Download en installeer het pakket.
Dit pakket heeft een commando “Normalize” ingebouwd. U kunt ook een van de vele methoden voor normalisatie kiezen, namelijk ‘center’ of ‘Z-score’
Volg het volgende voorbeeld:

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

Antwoord 15

De normaliserenfunctie van het BBMisc-pakket was de juiste tool voor mij omdat het kan omgaan met NA-waarden.

Zo gebruik je het:

Gezien de volgende dataset,

   ASR_API     <- c("CV",  "F",    "IER",  "LS-c", "LS-o")
    Human       <- c(NA,    5.8,    12.7,   NA, NA)
    Google      <- c(23.2,  24.2,   16.6,   12.1,   28.8)
    GoogleCloud <- c(23.3,  26.3,   18.3,   12.3,   27.3)
    IBM     <- c(21.8,  47.6,   24.0,   9.8,    25.3)
    Microsoft   <- c(29.1,  28.1,   23.1,   18.8,   35.9)
    Speechmatics    <- c(19.1,  38.4,   21.4,   7.3,    19.4)
    Wit_ai      <- c(35.6,  54.2,   37.4,   19.2,   41.7)
    dt     <- data.table(ASR_API,Human, Google, GoogleCloud, IBM, Microsoft, Speechmatics, Wit_ai)
> dt
   ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai
1:      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6
2:       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2
3:     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4
4:    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2
5:    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7

genormaliseerde waarden kunnen als volgt worden verkregen:

> dtn <- normalize(dt, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
> dtn
   ASR_API      Human     Google GoogleCloud         IBM  Microsoft Speechmatics      Wit_ai
1:      CV         NA  0.3361245   0.2893457 -0.28468670  0.3247336  -0.18127203 -0.16032655
2:       F -0.7071068  0.4875320   0.7715885  1.59862532  0.1700986   1.55068347  1.31594762
3:     IER  0.7071068 -0.6631646  -0.5143923 -0.12409420 -0.6030768   0.02512682 -0.01746131
4:    LS-c         NA -1.3444981  -1.4788780 -1.16064578 -1.2680075  -1.24018782 -1.46198764
5:    LS-o         NA  1.1840062   0.9323361 -0.02919864  1.3762521  -0.15435044  0.32382788

waarbij de met de hand berekende methode alleen colmuns negeert die NA’s bevatten:

> dt %>% mutate(normalizedHuman = (Human - mean(Human))/sd(Human)) %>% 
+ mutate(normalizedGoogle = (Google - mean(Google))/sd(Google)) %>% 
+ mutate(normalizedGoogleCloud = (GoogleCloud - mean(GoogleCloud))/sd(GoogleCloud)) %>% 
+ mutate(normalizedIBM = (IBM - mean(IBM))/sd(IBM)) %>% 
+ mutate(normalizedMicrosoft = (Microsoft - mean(Microsoft))/sd(Microsoft)) %>% 
+ mutate(normalizedSpeechmatics = (Speechmatics - mean(Speechmatics))/sd(Speechmatics)) %>% 
+ mutate(normalizedWit_ai = (Wit_ai - mean(Wit_ai))/sd(Wit_ai))
  ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai normalizedHuman normalizedGoogle
1      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6              NA        0.3361245
2       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2              NA        0.4875320
3     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4              NA       -0.6631646
4    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2              NA       -1.3444981
5    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7              NA        1.1840062
  normalizedGoogleCloud normalizedIBM normalizedMicrosoft normalizedSpeechmatics normalizedWit_ai
1             0.2893457   -0.28468670           0.3247336            -0.18127203      -0.16032655
2             0.7715885    1.59862532           0.1700986             1.55068347       1.31594762
3            -0.5143923   -0.12409420          -0.6030768             0.02512682      -0.01746131
4            -1.4788780   -1.16064578          -1.2680075            -1.24018782      -1.46198764
5             0.9323361   -0.02919864           1.3762521            -0.15435044       0.32382788

(normalizedHuman heeft een lijst met NA’s gemaakt …)

met betrekking tot de selectie van specifieke kolommen voor berekening, kan een generieke methode worden gebruikt zoals deze:

data_vars <- df_full %>% dplyr::select(-ASR_API,-otherVarNotToBeUsed)
meta_vars <- df_full %>% dplyr::select(ASR_API,otherVarNotToBeUsed)
data_varsn <- normalize(data_vars, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
dtn <- cbind(meta_vars,data_varsn)

Other episodes