R의 데이터 열 표준화


209

spam스팸 메시지와 관련된 58 열과 약 3500 행의 데이터를 포함 하는 데이터 세트 가 있습니다.

앞으로이 데이터 세트에서 선형 회귀를 실행할 계획이지만 사전 처리를 수행하고 평균 및 단위 분산이 0이 아닌 열을 표준화하고 싶습니다.

이 문제를 해결하는 가장 좋은 방법은 R을 사용한다는 것 입니다 .R로 정규화를 달성하는 방법 을 묻고 싶습니다 . 이미 데이터를 올바르게로드했으며이 작업을 수행 할 패키지 나 방법을 찾고 있습니다.

답변:


533

평균 0과 표준 편차 1을 원한다고 가정해야합니다. 데이터가 데이터 프레임에 있고 모든 열이 숫자 scale이면 데이터 에서 함수를 호출하여 원하는 것을 수행 할 수 있습니다.

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)

내장 함수를 사용하는 것이 고급입니다. 이 고양이처럼 :

여기에 이미지 설명을 입력하십시오


24
예, 제 실수는 0을 의미했습니다. 그리고 그것은 꽤 고급 고양이입니다
Hoser

8
:)이 뚱뚱한 고양이처럼 느리게도 할 수있다 적용 (여기 colMeans)를 사용하여 한
agstudy

1
@agstudy 박람회. colMeans / colSums를 더 많이 사용하는 습관을 가져야합니다. 내가 실제로 중요한 상황에 있지 않으면 그것을 생각하지 않는 것 같아요.
Dason

137
이 사이트는 더 많은 고양이가 필요합니다 +1
LoveMeow

35
경고 : scale은 또한 데이터 프레임을 행렬로 변환합니다
Julian Karls

88

질문이 오래되었고 하나의 답변이 수락됨을 알기 위해 참고할 다른 답변을 제공하겠습니다.

scale모든 변수의 크기를 조정한다는 사실에 의해 제한됩니다 . 아래의 솔루션을 사용하면 다른 변수는 변경하지 않고 특정 변수 이름 만 확장 할 수 있습니다 (변수 이름은 동적으로 생성 될 수 있음).

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

이것은 나에게 이것을 준다 :

> 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

> 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

편집 1 (2016) : Julian의 의견에 따르면 : 출력 scale은 Nx1 행렬이므로 이상적으로 as.vector행렬 유형을 다시 벡터 유형으로 변환 하려면를 추가해야합니다 . 줄리안 감사합니다!

편집 2 (2019) : 인용 Duccio A.의 의견 : 최신 dplyr (버전 0.8)의 경우 다음과 같이 목록으로 dplyr :: funcs를 변경해야합니다dat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))

편집 3 (2020) : @mj_whales 덕분에 : 이전 솔루션은 더 이상 사용되지 않으므로 이제 사용해야 mutate_at합니다.


이 방법은 특히 범주 형 변수와 숫자 형 변수의 조합이있을 때 완벽하게 작동합니다. 이 연산자의 의미가 "%> %"라는 질문이 하나 있습니다.
nooshinha 2016 년

9
@ weber85는 "파이프"연산자입니다 (기능적 프로그래밍). 글을 쓰는 대신 글을 쓰면 f(g(x))더 좋아 보일 것 x %>% g %>% f입니다. 다시 말해서, dat %>% mutate_each_(funs(scale),vars=c("y","z"))그냥 mutate_each_(dat,funs(scale),vars=c("y","z"))입니다. 체인이 매우 길면 f(g(h(i(j(x)))))읽기가 매우 어려울 수 있으므로 작업자가 많은 도움을줍니다 .

이 방법을 사용하면 스케일이 적용되는 열이 벡터 (클래스 숫자)에서 Nx1 행렬로 전송됩니다. 이로 인해 data.frame의 각 열이 벡터라고 가정하는 패키지에서 일부 오류가 발생할 수 있습니다.
Julian Karls

2
최신 dplyr(버전 0.8)의 경우 다음 dplyr::funcslist같이 변경해야합니다.dat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))
Duccio A

2
mutate_each_()더 이상 사용되지 않습니다. mutate_at()대신 사용할 수 있습니다 . 새로운 방법은 다음과 같습니다.dat2 <- dat %>% mutate_at(c("y", "z"), scale)
mj_whales

60

이것은 3 살입니다. 여전히 다음을 추가해야한다고 생각합니다.

가장 일반적인 정규화는 평균을 빼고 변수의 표준 편차로 나누는 z 변환 입니다. 결과는 mean = 0이고 sd = 1입니다.

이를 위해 패키지가 필요하지 않습니다.

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

그게 다야.


이것을 수행하는 완전히 간단한 방법. 감사합니다
Pedro Neves

그리고 그것을 훨씬 쉽게 사용할 수 있습니다 : mutate(var = (var - mean(var))/sd(var)).
RobertMyles 2016 년

그러나 이것이 두 변수에 대한 z 점수를 얻는 데 사용될 수 있습니까?
lf_araujo

비정규 화하는 것이 myVar <- (zVar * sd(zVar)) + mean(zVar)맞습니까?
Artur_Indio

4
@Artur_Indio 거의 : newVar <- (zVar * sd(myVar)) + mean(myVar). 원래 평균 / sd를 사용해야합니다. 당신이 그것을 작성, 당신은 곱하고 sd(zVar)=1추가 mean(zVar)=0하므로 아무것도 변경되지 않습니다 :)
random_forest_fanatic

24

'Caret'패키지는 데이터 전처리 방법 (예 : 중심 및 스케일링)을 제공합니다. 다음 코드를 사용할 수도 있습니다.

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

자세한 내용은 http://www.inside-r.org/node/86978


17

Dason이 언급 한 솔루션을 사용했을 때 결과적으로 데이터 프레임을 얻는 대신 숫자 벡터 (df의 배율 값)를 얻었습니다.

누군가 같은 문제가 발생하면 다음과 같이 as.data.frame ()을 코드에 추가해야합니다.

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

이것이 동일한 문제를 가진 ppl에 유용 할 수 있기를 바랍니다!


좋은 해결책! 누군가 축척에서 열을 제외시키려는 경우 다음과 같이 수행 할 수 있습니다. train_dt[-24] <- scale(train_dt[-24]) 여기서 "24"는 제외 할 열 번호
NetEmmanuel

13

clusterSim 패키지의 data.Normalization 함수를 사용하여 데이터를 쉽게 정규화 할 수 있습니다. 다른 데이터 정규화 방법을 제공합니다.

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

인수

x
벡터, 행렬 또는 데이터 세트 유형
정규화 : n0-정규화 없음

n1-표준화 ((x-mean) / sd)

n2-위치 표준화 ((x-median) / mad)

n3-단위 화 ((x-mean) / range)

n3a-위치 단위 화 ((x-median) / 범위)

n4-최소값이 0 인 단위 ((x-min) / 범위)

n5-<-1,1> 범위의 정규화 ((x-mean) / max (abs (x-mean)))

n5a-<-1,1> 범위의 위치 정규화 ((x-median) / max (abs (x-median)))

n6-몫 변환 (x / sd)

n6a-위치 몫 변환 (x / mad)

n7-몫 변환 (x / range)

n8-몫 변환 (x / max)

n9-몫 변환 (x / mean)

n9a-위치 몫 변환 (x / median)

n10-몫 변환 (x / sum)

n11-몫 변환 (x / sqrt (SSQ))

n12-정규화 ((x-mean) / sqrt (sum ((x-mean) ^ 2)))

n12a-위치 정규화 ((x-median) / sqrt (sum ((x-median) ^ 2)))

n13-중심점이 0 인 정규화 ((x-midrange) / (range / 2))

정규화
"열"-변수 별 정규화, "행"-객체 별 정규화


이 패키지는 R 버전 3.4.3
JdP

11

함께 dplyrv0.7.4 모든 변수를 사용하여 확장 할 수 있습니다 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

다음을 사용하여 특정 변수를 제외 할 수 있습니다 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

2018-04-24에 reprex 패키지 (v0.2.0)로 작성되었습니다.


9

다시 말하지만 이것은 오래된 질문이지만 매우 관련이 있습니다! 그리고 패키지가 필요없이 특정 열을 정규화하는 간단한 방법을 찾았습니다.

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

예를 들어

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)

y 및 z 열이 정규화되었음을 알 수 있습니다. 패키지가 필요하지 않습니다 :-)


8

스케일은 전체 데이터 프레임과 특정 열 모두에 사용할 수 있습니다. 특정 열의 경우 다음 코드를 사용할 수 있습니다.

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

전체 데이터 프레임

trainingSet <- scale(trainingSet)

3

dplyr패키지는 이렇게 두 가지 기능이 있습니다.

> require(dplyr)

데이터 테이블의 특정 열 을 변경하려면 함수를 사용할 수 있습니다 mutate_at(). 모든 열 을 변경하려면을 사용할 수 있습니다 mutate_all.

다음은 이러한 기능을 사용하여 데이터를 표준화하는 간단한 예입니다.

특정 열을 변경합니다.

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 

모든 열을 변경하십시오.

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 

1

이 스레드를 찾기 전에 같은 문제가있었습니다. 사용자 종속 열 유형이 있었으므로 for루프를 작성하여 필요한 열을 얻었습니다 scale. 더 좋은 방법이있을 수 있지만 문제를 해결했습니다.

 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그것은 필요한 부분입니다. 왜냐하면 보통 당신이 갖고 싶지 않은 행렬을 scale수행 하기 때문 입니다.rownames x 1data.frame


0

"recommenderlab"패키지를 사용하십시오. 패키지를 다운로드하여 설치하십시오. 이 패키지에는 "Normalize"명령이 내장되어 있습니다. 또한 표준화를위한 많은 방법 중 하나 인 'center'또는 'Z-score'를 선택할 수 있습니다. 다음 예를 따르십시오.

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

1
이 답변은 질문을 다루지 않습니다.
f0nzie

0

BBMisc 패키지 의 정규화 기능은 NA 값을 처리 할 수 ​​있기 때문에 나에게 적합한 도구였습니다.

사용 방법은 다음과 같습니다.

다음과 같은 데이터 세트가 주어지면

    ASR_API     <- c("CV",  "F",    "IER",  "LS-c", "LS-o")
    Human       <- c(NA,    5.8,    12.7,   NA, NA)
    Google      <- c(23.2,  24.2,   16.6,   12.1,   28.8)
    GoogleCloud <- c(23.3,  26.3,   18.3,   12.3,   27.3)
    IBM     <- c(21.8,  47.6,   24.0,   9.8,    25.3)
    Microsoft   <- c(29.1,  28.1,   23.1,   18.8,   35.9)
    Speechmatics    <- c(19.1,  38.4,   21.4,   7.3,    19.4)
    Wit_ai      <- c(35.6,  54.2,   37.4,   19.2,   41.7)
    dt     <- data.table(ASR_API,Human, Google, GoogleCloud, IBM, Microsoft, Speechmatics, Wit_ai)
> dt
   ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai
1:      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6
2:       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2
3:     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4
4:    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2
5:    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7

정규화 된 값은 다음과 같이 얻을 수 있습니다.

> dtn <- normalize(dt, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
> dtn
   ASR_API      Human     Google GoogleCloud         IBM  Microsoft Speechmatics      Wit_ai
1:      CV         NA  0.3361245   0.2893457 -0.28468670  0.3247336  -0.18127203 -0.16032655
2:       F -0.7071068  0.4875320   0.7715885  1.59862532  0.1700986   1.55068347  1.31594762
3:     IER  0.7071068 -0.6631646  -0.5143923 -0.12409420 -0.6030768   0.02512682 -0.01746131
4:    LS-c         NA -1.3444981  -1.4788780 -1.16064578 -1.2680075  -1.24018782 -1.46198764
5:    LS-o         NA  1.1840062   0.9323361 -0.02919864  1.3762521  -0.15435044  0.32382788

여기서 수동 계산 방법은 NA가 포함 된 콜문을 무시합니다.

> dt %>% mutate(normalizedHuman = (Human - mean(Human))/sd(Human)) %>% 
+ mutate(normalizedGoogle = (Google - mean(Google))/sd(Google)) %>% 
+ mutate(normalizedGoogleCloud = (GoogleCloud - mean(GoogleCloud))/sd(GoogleCloud)) %>% 
+ mutate(normalizedIBM = (IBM - mean(IBM))/sd(IBM)) %>% 
+ mutate(normalizedMicrosoft = (Microsoft - mean(Microsoft))/sd(Microsoft)) %>% 
+ mutate(normalizedSpeechmatics = (Speechmatics - mean(Speechmatics))/sd(Speechmatics)) %>% 
+ mutate(normalizedWit_ai = (Wit_ai - mean(Wit_ai))/sd(Wit_ai))
  ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai normalizedHuman normalizedGoogle
1      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6              NA        0.3361245
2       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2              NA        0.4875320
3     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4              NA       -0.6631646
4    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2              NA       -1.3444981
5    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7              NA        1.1840062
  normalizedGoogleCloud normalizedIBM normalizedMicrosoft normalizedSpeechmatics normalizedWit_ai
1             0.2893457   -0.28468670           0.3247336            -0.18127203      -0.16032655
2             0.7715885    1.59862532           0.1700986             1.55068347       1.31594762
3            -0.5143923   -0.12409420          -0.6030768             0.02512682      -0.01746131
4            -1.4788780   -1.16064578          -1.2680075            -1.24018782      -1.46198764
5             0.9323361   -0.02919864           1.3762521            -0.15435044       0.32382788

(normalizedHuman은 NA 목록으로 만들어집니다 ...)

계산할 특정 열의 선택과 관련하여 다음과 같은 일반적인 방법을 사용할 수 있습니다.

data_vars <- df_full %>% dplyr::select(-ASR_API,-otherVarNotToBeUsed)
meta_vars <- df_full %>% dplyr::select(ASR_API,otherVarNotToBeUsed)
data_varsn <- normalize(data_vars, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
dtn <- cbind(meta_vars,data_varsn)

0

@BBKim은 가장 좋은 답변을 주었지만 더 짧게 할 수 있습니다. 아직 아무도 그 소식을 낸 것에 놀랐습니다.

dat <- data.frame(x = rnorm(10, 30, .2), y = runif(10, 3, 5)) dat <- apply(dat, 2, function(x) (x - mean(x)) / sd(x))

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.