266 votes

Normaliser 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 relatives aux messages de spam.

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

On m'a dit que le meilleur moyen d'y parvenir est d'utiliser R, donc je voudrais demander comment puis-je réaliser la normalisation avec R ? J'ai déjà chargé les données correctement et je cherche simplement des paquets ou des méthodes pour effectuer cette tâche.

638voto

Dason Points 18263

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 très classe. Comme ce chat :

enter image description here

124voto

akhmed Points 3238

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

scale est limitée par le fait qu'elle est mise à l'échelle toutes les variables . La solution ci-dessous permet de mettre à l'échelle uniquement des noms de variables spécifiques tout en conservant les autres variables inchangées (et les noms de variables pourraient ê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_at(c("y", "z"), ~(scale(.) %>% as.vector))
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_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) : Réponse au commentaire de Julian : la sortie de l'application scale est une matrice Nx1. Idéalement, nous devrions donc ajouter un élément as.vector pour reconvertir le type de matrice en type de vecteur. Merci Julian !

EDIT 2 (2019) : Citant le commentaire de Duccio A. : Pour la dernière version de dplyr (version 0.8), vous devez remplacer dplyr::funcs par list, comme suit dat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))

EDIT 3 (2020) : Merci à @mj_whales : l'ancienne solution est dépréciée et il faut maintenant utiliser mutate_at .

74voto

fmb Points 801

Cela date de 3 ans. Pourtant, je me sens obligé d'ajouter ce qui suit :

La normalisation la plus courante est la Transformation en z où vous soustrayez la moyenne et divisez par l'écart-type de votre variable. Le résultat aura une moyenne=0 et un écart-type=1.

Pour cela, vous n'avez pas besoin de paquet.

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

C'est tout.

28voto

DaniM Points 426

Le paquet 'Caret' fournit des méthodes pour le prétraitement des données (par exemple, le centrage et la 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

25voto

Diego Points 319

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

Au cas où quelqu'un aurait 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 !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X