标准化R中的数据列

Hos*_*ser 185 r normalization

我有一个名为的数据集spam,其中包含58个列和大约3500行与垃圾邮件相关的数据.

我打算将来在这个数据集上运行一些线性回归,但我想事先做一些预处理,并将列标准化为零均值和单位方差.

我被告知最好的方法是使用R,所以我想问一下如何用R实现规范化?我已经正确加载了数据,我只是在寻找一些包或方法来执行此任务.

Das*_*son 487

我必须假设您想要表示平均值为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)
Run Code Online (Sandbox Code Playgroud)

使用内置函数是优雅的.喜欢这只猫:

在此输入图像描述

  • 这个网站需要更多的猫+1 (129认同)
  • 我正在低估,因为我觉得这只猫很讨厌.-1 (60认同)
  • 警告:scale还会将数据帧转换为矩阵 (30认同)
  • 是的我的错误我的意思是0意思.这是一只非常优雅的猫 (21认同)
  • +1使用申请也可能很慢也像这只胖猫:)(colMeans这里) (7认同)
  • 爱猫,这个答案! (2认同)

akh*_*med 78

意识到问题是陈旧的,一个答案被接受,我将提供另一个答案供参考.

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
Run Code Online (Sandbox Code Playgroud)

这给了我这个:

> 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
Run Code Online (Sandbox Code Playgroud)

> 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
Run Code Online (Sandbox Code Playgroud)

编辑:解决了Julian的评论:输出scale是Nx1矩阵,所以理想情况下我们应该添加一个as.vector将矩阵类型转换回矢量类型.谢谢朱利安!

  • @ weber85,它是一个"管道"操作符(来自函数式编程).如果写一个'x%>%g%>%f`,它会更好看,而不是写'f(g(x))`.换句话说,`dat%>%mutate_each_(funs(scale),vars = c("y","z"))`只是`mutate_each_(dat,funs(scale),vars = c("y", "Z"))`.当链很长时,操作员会帮助很多,因为`f(g(i(j(x))))``可能非常难以阅读. (8认同)
  • 对于最新的dplyr(0.8版),您需要使用list来更改dplyr :: funcs,例如dat%&gt;%mutate_each_(list(〜scale(。)%&gt;%as.vector),vars = c(“ y”,“ z”))` (2认同)
  • `mutate_each_()` 现已弃用。您可以使用“mutate_at()”代替。新的方法是: `dat2 &lt;- dat %&gt;% mutate_at(c("y", "z"), scale)` (2认同)
  • “dplyr”的格局再次发生变化。在“dplyr 1.0.0”(正在开发中)中,“mutate(across(x:y,scale))”现在似乎是正确的解决方案。 (2认同)

小智 57

这是3岁.不过,我觉得我必须添加以下内容:

最常见的归一化是z变换,您可以减去均值并除以变量的标准差.结果将是mean = 0和sd = 1.

为此,您不需要任何包.

zVar <- (myVar - mean(myVar)) / sd(myVar)
Run Code Online (Sandbox Code Playgroud)

而已.

  • @Artur_Indio差不多:`newVar &lt;-(zVar * sd(myVar))+ mean(myVar)` 您必须使用原始均值/标准差。在编写过程中,您将乘以sd(zVar)= 1`并加上`mean(zVar)= 0`,所以什么都不会改变:) (3认同)

小智 21

'Caret'包提供了预处理数据的方法(例如居中和缩放).您还可以使用以下代码:

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

更多细节:http://www.inside-r.org/node/86978


小智 15

当我使用Dason所说的解决方案时,我得到了一个数字向量(我的df的缩放值),而不是得到一个数据帧.

如果有人遇到同样的问题,你必须在代码中添加as.data.frame(),如下所示:

df.scaled <- as.data.frame(scale(df))
Run Code Online (Sandbox Code Playgroud)

我希望这对有同样问题的人有用!

  • 很好的解决方案!如果有人想要从缩放中排除一列,您可以这样做:``train_dt[-24] &lt;-scale(train_dt[-24])```其中“24”是要排除的列号 (3认同)

Sam*_*agd 13

您还可以使用clusterSim包中的data.Normalization函数轻松规范化数据.它提供了不同的数据规范化方法.

    data.Normalization (x,type="n0",normalization="column")
Run Code Online (Sandbox Code Playgroud)

参数

x
向量,矩阵或数据集类型
的归一化类型:n0 - 没有归一化

n1 - 标准化((x-mean)/ sd)

n2 - 位置标准化((x-median)/ mad)

n3 - 单位化((x-mean)/ range)

n3a - 位置单位化((x-median)/ range)

n4 - 最小零((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 /范围)

n8 - 商变换(x/max)

n9 - 商变换(x /均值)

n9a - 位置商变换(x /中位数)

n10 - 商变换(x/sum)

n11 - 商变换(x/sqrt(SSQ))

n12 - 归一化((x-mean)/ sqrt(sum((x-mean)^ 2)))

n12a - 位置归一化((x-median)/ sqrt(sum((x-median)^ 2)))

n13 - 归零,零为中心点((x-midrange)/(range/2))

规范化
"列" - 按变量归一化,"行" - 按对象归一化


pat*_*t-s 8

使用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
Run Code Online (Sandbox Code Playgroud)

可以使用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
Run Code Online (Sandbox Code Playgroud)

reprex软件包(v0.2.0)创建于2018-04-24。


小智 7

同样,即使这是一个老问题,它也是非常相关的!我找到了一种简单的方法来规范化某些列而无需任何包:

normFunc <- function(x){(x-mean(x, na.rm = T))/sd(x, na.rm = T)}
Run Code Online (Sandbox Code Playgroud)

例如

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)
Run Code Online (Sandbox Code Playgroud)

您将看到y和z列已标准化.不需要包裹:-)


Ami*_*mit 6

比例可用于完整数据框和特定列。对于特定的列,可以使用以下代码:

trainingSet[, 3:7] = scale(trainingSet[, 3:7]) # For column 3 to 7
trainingSet[, 8] = scale(trainingSet[, 8]) # For column 8 
Run Code Online (Sandbox Code Playgroud)

全数据帧

trainingSet <- scale(trainingSet)
Run Code Online (Sandbox Code Playgroud)