Normalizar as colunas de dados em R

Tenho um conjunto de dados chamado spam que contém 58 colunas e aproximadamente 3500 linhas de dados relacionados com mensagens de spam.

eu planeio correr alguma regressão linear neste conjunto de dados no futuro, mas gostaria de fazer algum pré-processamento de antemão e padronizar as colunas para ter a média zero e variância de unidade.

disseram-me que a melhor maneira de fazer isto é com o R, por isso gostaria de perguntar Como posso conseguir a normalização Com O R? Já tenho os dados. devidamente carregado e eu estou apenas procurando alguns pacotes ou métodos para executar esta tarefa.

Author: Hoser, 2013-03-05

12 answers

Tenho de assumir que querias dizer que querias uma média de 0 e um desvio padrão de 1. Se os seus dados estiverem num dataframe e todas as colunas forem numéricas, poderá simplesmente chamar a função scale nos dados para fazer o que quiser.
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)

Usar funções incorporadas tem Classe. Como este gato:

enter image description here

 393
Author: Dason, 2013-03-05 03:55:05
Percebendo que a pergunta é antiga e que uma resposta é aceite, darei outra resposta para referência.

scale é limitado pelo fato de que escala todas as variáveis. A solução abaixo permite escalar apenas nomes de variáveis específicas preservando outras variáveis inalteradas (e os nomes de variáveis poderiam ser gerados dinamicamente):

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
O que me dá isto:
> 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

E

> 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 : endereçou o comentário do Julian: a a saída de scale é a matriz Nx1 então, idealmente, devemos adicionar um as.vector para converter o tipo de matriz de volta em um tipo vetorial. Obrigado Julian!

 60
Author: akhmed, 2016-12-01 06:08:58
Isto tem 3 anos. Ainda assim, sinto que tenho de acrescentar o seguinte:

A normalização mais comum é a z-transformação , onde subtrai a média e divide pelo desvio padrão da sua variável. O resultado terá média = 0 e sd=1.

Para isso, não precisas de nenhum pacote.
zVar <- (myVar - mean(myVar)) / sd(myVar)
É isso.
 41
Author: fmb, 2016-06-02 20:22:29

O pacote "Caret" contém métodos para o pré-processamento de dados (por exemplo, centralização e escala). Você também pode usar o seguinte código:

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

Mais detalhes: http://www.inside-r.org/node/86978

 18
Author: DaniM, 2017-05-12 12:53:13

Você pode facilmente normalizar os dados também usando dados.Função de normalização no Pacote clusterSim. Ele fornece diferentes métodos de normalização de dados.

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

Argumentos

X
vector, matriz ou conjunto de dados tipo
tipo de normalização: n0-sem normalização

N1 - normalização ((x-média)/sd)

N2 - normalização posicional [(x-mediana)/mad]

N3-unitization ((x-mean)/range)

N3A-unitization posicional

N4-unitization with zero minimum ((x-min)/range)

N5 - normalização no intervalo ((x-média)/max(abs(x-média)))

N5A - normalização posicional no intervalo ((x-mediana)/max(abs(x-mediana)))

Transformação N6 - quociente (x/sd)

N6A-transformação do quociente posicional (x/mad)

Transformação N7 - quociente (x/Gama)

Transformação N8 - quociente (x/max)

Transformação N9-quociente (x/média)

N9a - transformação do quociente posicional (x / mediana)

Transformação N10 - quociente (x/sum)

N11 - transformação do quociente [x / sqrt (SSQ)]

N12-normalização ((x-média)/sqrt (Soma (x-média))^2)))

N12a-normalização posicional ((mediana x)/sqrt (soma (mediana x))^2)))

N13-normalização com zero sendo o ponto central(x-midrange)/(intervalo/2))

Normalização
"coluna" - normalização por variável,"linha" - normalização pelo objecto

 11
Author: Samehmagd, 2016-02-16 08:11:17

Quando eu usei a solução indicada por Dason, em vez de obter uma moldura de dados como resultado, eu tenho um vetor de Números (os valores escalados do meu df).

No caso de alguém estar a ter o mesmo problema, tens de adicionar as.dado.frame () para o código, assim:
df.scaled <- as.data.frame(scale(df))
Espero que isto seja útil para a ppl ter o mesmo problema!
 10
Author: Diego, 2016-10-31 14:16:49

Com dplyr v0. 7. 4 todas as variáveis podem ser dimensionadas usando 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

Podem ser excluídas variáveis específicas utilizando 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

Criado em 2018-04-24 pelo pacote reprex (v0.2.0).

 4
Author: pat-s, 2018-04-24 13:03:33
Mais uma vez, embora esta seja uma pergunta antiga, é muito relevante! E eu encontrei uma maneira simples de normalizar certas colunas sem a necessidade de quaisquer pacotes:
normFunc <- function(x){(x-mean(x, na.rm = T))/sd(x, na.rm = T)}

Por exemplo

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)

Verá que as colunas y E z foram normalizadas. Não são necessários pacotes: -)

 2
Author: BBKim, 2018-07-04 16:43:11
Antes de encontrar este fio, tinha o mesmo problema. Eu tinha tipos de colunas dependentes do usuário, então eu escrevi um loop for passando por eles e obtendo as colunas necessárias scale'd. provavelmente existem maneiras melhores de fazê-lo, mas isso resolveu o problema muito bem:
 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 é uma parte necessária, porque acontece scale faz rownames x 1 matriz que normalmente não é o que você quer ter em seu data.frame.

 1
Author: Claud H, 2017-06-12 14:40:15

A escala pode ser utilizada tanto para a moldura de dados completa como para colunas específicas. Para colunas específicas, pode ser utilizado o seguinte código:

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

Quadro completo de dados

trainingSet <- scale(trainingSet)
 1
Author: Amit, 2017-10-19 14:21:20

Utilize a embalagem "recommenderlab". Baixe e instale o pacote. Este pacote tem um comando "normalizar" incorporado. Ele também permite que você escolha um dos muitos métodos para a normalização, ou seja, 'centro' ou 'Z-score' Siga o seguinte exemplo:

## 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
Author: user3601993, 2015-09-18 12:13:50

O pacote dplyr tem duas funções que fazem isto.

> require(dplyr)

Para mutarcolunas específicas de uma tabela de dados, pode usar a função mutate_at(). Para mutar todas as colunas , pode usar mutate_all.

O seguinte é um breve exemplo para usar estas funções para padronizar os dados.

Modificar as colunas específicas:

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 

Modificar todas as colunas:

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
Author: Jack, 2018-08-30 21:18:18