Standardiser les colonnes de données dans R

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

Je prévois d'exécuter une régression linéaire sur cet ensemble de données à l'avenir, mais je voudrais faire un pré-traitement à l'avance et standardiser les colonnes pour avoir une moyenne nulle et une variance unitaire.

On m'a dit que la meilleure façon de procéder est avec R, donc je voudrais demander Comment puis-je atteindre la normalisation avec R? J'ai déjà les données correctement chargé et je cherche juste des paquets ou des méthodes pour effectuer cette tâche.

134
demandé sur Hoser 2013-03-05 07:45:45

12 réponses

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 dataframe et toutes les colonnes sont numériques, vous pouvez simplement appeler la scale function 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)

L'utilisation de fonctions intégrées est chic. Comme ce chat:

entrez la description de l'image ici

393
répondu Dason 2013-03-05 03:55:05

Réalisant que la question Est ancienne et qu'une réponse est acceptée, je vais fournir une autre réponse pour 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 inchangées (et les noms de variables peuvent être générés dynamiquement):

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

60
répondu akhmed 2016-12-01 06:08:58

, C'est 3 ans. Pourtant, je pense que je dois ajouter ce qui suit:

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

Pour cela, vous n'avez besoin d'Aucun paquet.

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

C'est ça.

41
répondu fmb 2016-06-02 20:22:29

Le paquet '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
répondu DaniM 2017-05-12 12:53:13

Vous pouvez facilement normaliser les données en utilisant également les données.Fonction de normalisation dans le paquet 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-moyenne)/écart-type)

N2-standardisation positionnelle ((x-médiane)/mad)

N3 - unissant ((x-moyenne)/plage)

N3a-Unité de position ((x-médiane)/plage)

N4-unitisation avec zéro minimum ((X-min)/gamme)

N5-normalisation dans la plage ((x-mean)/max(abs(X-mean)))

N5A-normalisation de position dans la plage ((x-médiane)/max(abs(X-médiane)))

N6 - transformation du quotient (x / sd)

N6A-transformation du quotient positionnel (x/mad)

N7 - transformation du quotient (x / plage)

N8 - transformation du quotient (x / max)

N9 - transformation du quotient (x/moyenne)

N9A-transformation du quotient de position (X / médiane)

N10 - transformation du quotient (x / somme)

N11-transformation du quotient (x / sqrt (SSQ))

N12 - normalisation ((x-moyenne)/sqrt(sum((x-moyenne)^2)))

N12a - position de la normalisation ((x-médiane)/sqrt(sum((x-médiane)^2)))

N13-normalisation avec zéro étant le point central ((X-milieu de gamme)/(GAMME/2))

Normalisation
"colonne" - normalisation par variable, " ligne" - normalisation par objet

11
répondu Samehmagd 2016-02-16 08:11:17

Quand j'ai utilisé la solution indiquée par Dason, au lieu d'obtenir une trame de données en conséquence, j'ai obtenu un vecteur de nombres (les valeurs mises à l'échelle de mon df).

Dans le cas où quelqu'un a le même problème, vous devez ajouter.données.frame() au code, comme ceci:

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

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

10
répondu Diego 2016-10-31 14:16:49

Avec dplyr v0. 7. 4 toutes les variables peuvent être mises à l'échelle en utilisant 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

Les variables spécifiques peuvent être exclues en utilisant 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 paquet reprex (v0. 2. 0).

4
répondu pat-s 2018-04-24 13:03:33

Encore une fois, même si c'est une vieille question, il est très pertinent! Et j'ai trouvé un moyen simple de normaliser certaines colonnes sans avoir besoin de paquets:

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 paquet nécessaire: -)

2
répondu BBKim 2018-07-04 16:43:11

Avant de trouver ce fil, j'ai eu le même problème. J'avais des types de colonnes dépendants de l'utilisateur, donc j'ai écrit une boucle for en les parcourant et en obtenant les colonnes nécessaires scale ' D. Il y a probablement de meilleures façons de le faire, mais cela a très bien résolu le problème:

 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é scale ne rownames x 1 de la matrice qui n'est généralement pas ce que vous voulez avoir dans votre data.frame.

1
répondu Claud H 2017-06-12 14:40:15

Scale peut être utilisé à la fois pour la trame de données complète 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)
1
répondu Amit 2017-10-19 14:21:20

Utilisez le paquet "recommenderlab". Téléchargez et installez le package. Ce paquet a une commande "Normalize" dans built. Il vous permet également de choisir l'une des nombreuses méthodes de normalisation à savoir "centre" ou "Z-score" 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
répondu user3601993 2015-09-18 12:13:50

Le paquet dplyr a deux fonctions qui le font.

> require(dplyr)

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

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

Muter 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 

Muter 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
répondu Jack 2018-08-30 21:18:18