web-dev-qa-db-fra.com

Normaliser les colonnes de données dans R

J'ai un ensemble de données appelé spam qui contient 58 colonnes et environ 3 500 lignes de données relatives aux messages de spam. 

Je prévois d’exécuter une régression linéaire sur cet ensemble de données à l’avenir, mais j’aimerais faire un prétraitement au préalable et normaliser les colonnes pour qu’elles aient une variance moyenne et unité nulle. 

On m'a dit que la meilleure façon de procéder est avec R, alors j'aimerais demander comment puis-je obtenir une normalisation avec R ? Les données sont déjà correctement chargées et je recherche simplement des packages ou des méthodes pour effectuer cette tâche. 

150
Hoser

Je suppose que vous vouliez dire que vous vouliez une moyenne de 0 et un écart type de 1. Si vos données sont dans un cadre de données et que toutes les colonnes sont numériques, vous pouvez simplement appeler la fonction scale sur les données pour faire ce que vous voulez .

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)

Utiliser les fonctions intégrées est classe. Comme ce chat:

enter image description here

428
Dason

Réalisant que la question est ancienne et qu'une réponse est acceptée, je vais donner une autre réponse à titre de référence.

scale est limité par le fait qu'il met à l'échelle toutes les variables . La solution ci-dessous permet de mettre à l'échelle uniquement des noms de variables spécifiques tout en préservant les autres variables (les noms de variables pouvant être générés de manière dynamique):

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

ce qui me donne ceci:

> 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

et 

> 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: Commentaire de Julian adressé: la sortie de scale est une matrice Nx1, donc nous devrions idéalement ajouter un as.vector pour reconvertir le type de matrice en un type vectoriel. Merci Julian!

64
akhmed

C'est 3 ans. Néanmoins, j’ai le sentiment que je dois ajouter ce qui suit:

La normalisation la plus courante est la transformation z , où vous soustrayez la moyenne et divisez par l'écart type de votre variable. Le résultat aura moyenne = 0 et sd = 1.

Pour cela, vous n'avez besoin d'aucun colis.

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

C'est tout.

49
fmb

Le package 'Caret' fournit des méthodes de prétraitement des données (par exemple, centrage et mise à l’échelle). Vous pouvez également utiliser le code suivant:

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

Plus de détails: http://www.inside-r.org/node/86978

18
DaniM

Lorsque j'ai utilisé la solution indiquée par Dason, au lieu d'obtenir un bloc de données, j'ai obtenu un vecteur de nombres (les valeurs mises à l'échelle de mon fichier df).

Si quelqu'un rencontre le même problème, vous devez ajouter as.data.frame () au code, comme ceci:

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

J'espère que cela sera utile pour les personnes ayant le même problème!

12
Diego

Vous pouvez facilement normaliser les données en utilisant également la fonction data.Normalization dans le package clusterSim. Il fournit une méthode différente de normalisation des données.

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

Arguments

x
vecteur, matrice ou jeu de données type
type de normalisation: n0 - sans normalisation

n1 - normalisation ((x-mean)/sd)

n2 - normalisation de position ((médiane)/mad)

n3 - unitisation ((moyenne x)/plage)

n3a - unitisation positionnelle ((médiane x)/plage)

n4 - unitisation avec zéro minimum ((x-min)/plage)

n5 - normalisation dans la plage <-1,1> ((x-moyenne)/max (abs (x-moyenne)))

n5a - normalisation de position dans la plage <-1,1> ((x-médiane)/max (abs (x-médiane)))

n6 - transformation de quotient (x/sd)

n6a - transformation du quotient de position (x/mad)

n7 - transformation du quotient (x/range)

n8 - transformation de quotient (x/max)

n9 - transformation du quotient (x/moyenne)

n9a - transformation du quotient de position (x/médiane)

n10 - transformation du quotient (x/sum)

n11 - transformation de quotient (x/sqrt (SSQ))

n12 - normalisation ((x-moyenne)/sqrt (somme ((x-moyenne) ^ 2)))

n12a - normalisation de position ((x-médiane)/sqrt (somme ((x-médiane) ^ 2)))

n13 - normalisation avec zéro étant le point central ((médium x)/(plage/2))

normalisation
"colonne" - normalisation par variable, "rangée" - normalisation par objet

11
Samehmagd

Encore une fois, même si cette question est ancienne, elle est très pertinente! Et j'ai trouvé un moyen simple de normaliser certaines colonnes sans avoir besoin de paquet:

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

Par exemple

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)

Vous verrez que les colonnes y et z ont été normalisées. Aucun forfait requis :-)

5
BBKim

Avec dplyr v0.7.4, toutes les variables peuvent être mises à l'échelle à l'aide de 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

Des variables spécifiques peuvent être exclues à l'aide de 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

Créé le 2018-04-24 par le package reprex (v0.2.0).

4
pat-s

L'échelle peut être utilisée à la fois pour le cadre de données complet et pour des colonnes spécifiques . Pour des colonnes spécifiques, le code suivant peut être utilisé:

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

Cadre de données complet

trainingSet <- scale(trainingSet)
2
Amit

Avant de trouver ce fil, j'avais le même problème. J'avais des types de colonne dépendants de l'utilisateur, alors j'ai écrit une boucle for qui les parcourait et obtenait les colonnes nécessaires scale 'd. Il y a probablement de meilleures façons de le faire, mais cela résout le problème très bien:

 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 est une partie nécessaire, car il s'est avéré que scale fait rownames x 1 matrice, ce qui n'est généralement pas ce que vous voulez avoir dans votre data.frame.

1
Claud H

Utilisez le package "recommenderlab". Téléchargez et installez le paquet . Ce paquet a une commande "Normaliser" dans construit. Il vous permet également de choisir l’une des nombreuses méthodes de normalisation, à savoir «centre» ou «score Z» Suivez l’exemple suivant:

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

Le package dplyr a deux fonctions pour cela.

> require(dplyr)

Pour muter des colonnes spécifiques d'une table de données, vous pouvez utiliser la fonction mutate_at(). Pour muter les colonnes all, vous pouvez utiliser mutate_all.

Voici un bref exemple d'utilisation de ces fonctions pour normaliser les données.

Mutez des colonnes spécifiques:

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 

Mutez toutes les colonnes:

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