web-dev-qa-db-ja.com

Rのデータ列を標準化する

スパムメッセージに関連する58列と約3500行のデータを含むspamというデータセットがあります。

将来このデータセットに対して線形回帰を実行する予定ですが、事前に前処理を行い、平均と単位の分散がゼロになるように列を標準化したいと思います。

私はこれを実行する最良の方法はRであると言われました、それで私は に依頼したいのですが - どのように私はRで正規化を達成することができます ?データは正しくロードされています。このタスクを実行するためのパッケージまたはメソッドを探しています。

166
Hoser

データがデータフレーム内にあり、すべての列が数値である場合は、データに対して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)

組み込み関数の使用は上品です。この猫のように:

enter image description here

442
Dason

質問が古く、1つの回答が受け入れられたことを認識した上で、参考のために別の回答を提供します。

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_each_(funs(scale(.) %>% as.vector), 
                             vars=c("y","z"))
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_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 1(2016) :Julian氏のコメント:scaleの出力はNx1行列なので、理想的には行列型をベクトル型に変換するためにas.vectorを追加するべきです。ありがとうJulian!

編集2(2019) :引用Duccio A.のコメント:最新のdplyr(バージョン0.8)では、dat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))のようにdplyr :: funcsをlistで変更する必要があります。

66
akhmed

これは3歳です。それでも、私は以下を追加する必要があると感じます:

最も一般的な正規化は、 z変換 です。ここで、平均値を引き、変数の標準偏差で除算します。結果はmean = 0とsd = 1になります。

そのためには、パッケージは必要ありません。

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

それでおしまい。

52
fmb

「キャレット」パッケージは、データを前処理する方法(例えば、センタリングおよびスケーリング)を提供する。次のようなコードも使えます。

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

20
DaniM

結果としてデータフレームを取得する代わりに、Dasonが述べた解を使用すると、数値のベクトル(dfのスケール値)が得られました。

誰かが同じ問題を抱えている場合は、次のようにコードにas.data.frame()を追加する必要があります。

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

私はこれが同じ問題を抱えているpplに役立つことを願っています!

15
Diego

ClusterSimパッケージのdata.Normalization関数を使用してデータを簡単に正規化することもできます。それはデータ正規化の異なる方法を提供します。

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

引数

バツ
ベクトル、行列またはデータセット型
正規化タイプ:n0 - 正規化なし

n1 - 標準化((x-mean)/ sd)

n2 - 位置標準化((x-median)/ mad)

n3 - ユニット化((x-mean)/ range)

n3a - 位置単位化((x中央値)/範囲)

n4 - 最小値ゼロの単位化((x-min)/ range)

n 5 - 範囲<-1,1>((x平均)/ max(abs(x平均)))での正規化

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 /中央値)

n10 - 商変換(x/sum)

n11 - 商変換(x/sqrt(SSQ))

n 12 - 正規化((x平均)/ sqrt(sum((x平均)^ 2)))

n12a - 位置正規化((x-median)/ sqrt(sum((x-median)^ 2)))

n13 - ゼロを中心点とする正規化((x-midrange)/(range/2))

正規化
"列" - 変数による正規化、 "行" - オブジェクトによる正規化

12
Samehmagd

繰り返しますが、これは古い質問ですが、非常に重要です。そして、パッケージを必要とせずに特定の列を正規化する簡単な方法を見つけました。

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列が正規化されたことがわかります。パッケージは必要ありません:-)

7
BBKim

dplyr v0.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に Representxパッケージ (v0.2.0)によって作成されました。

6
pat-s

スケールは、フルデータフレームと特定の列の両方に使用できます。特定の列には、次のコードを使用できます。

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

フルデータフレーム

trainingSet <- scale(trainingSet)
3
Amit

偶然このスレッドを見つける前に、私は同じ問題を抱えていました。私はユーザ依存のカラム型を持っていたので、それらを通り抜けて必要なカラムを取得するforname__ループを書きましたscalename__。もっと良い方法があるかもしれませんが、これで問題は解決しました。

 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は必要な部分です、なぜならscalename__はrownames x 1行列を処理するからです。これは通常あなたがあなたのdata.frameに持っていたいものではありません。

1
Claud H

dplyrパッケージにはこれを行う2つの関数があります。

> require(dplyr)

データテーブルの specific columnsを変更するには、関数mutate_at()を使います。 all columnsを変更するには、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
Jack

パッケージ "recommenderlab"を使用してください。パッケージをダウンロードしてインストールします。このパッケージには "Normalize"というコマンドが組み込まれています。それはあなたが正規化のための多くの方法のうちの1つを選ぶことを可能にします、すなわち、「センター」または「Zスコア」以下の例に従ってください:

## 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
user3601993