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.
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:
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!
, 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.
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
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
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!
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).
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: -)
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
.
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)
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=”), items=paste('i', 1:10, sep=”)))
## 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")
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