我有一个名为spam
的数据集,其中包含58个列和大约3500行与垃圾邮件相关的数据。
我计划将来对此数据集运行一些线性回归,但我希望事先进行一些预处理,并将列标准化为零均值和单位方差。
我被告知最好的方法是使用R,所以我想问如何用R 实现规范化?我已经正确加载了数据,我只是在寻找一些包或方法来执行此任务。
答案 0 :(得分:443)
我必须假设您想要表示平均值为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)
使用内置函数非常优雅。像这只猫:
答案 1 :(得分:66)
意识到问题已经过时并且接受了一个答案,我将提供另一个答案以供参考。
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
编辑1(2016):解答Julian的评论:scale
的输出是Nx1矩阵,所以理想情况下我们应该添加as.vector
来转换矩阵键入一个矢量类型。谢谢Julian!
编辑2(2019):引用Duccio A。评论:对于最新的dplyr(版本0.8),您需要使用list更改dplyr :: funcs,例如{{1 }}
答案 2 :(得分:52)
这是3岁。不过,我觉得我必须添加以下内容:
最常见的归一化是 z-transformation ,其中您减去均值并除以变量的标准差。结果将是mean = 0和sd = 1.
为此,您不需要任何包。
zVar <- (myVar - mean(myVar)) / sd(myVar)
就是这样。
答案 3 :(得分:20)
&#39;插入符&#39; package提供了预处理数据的方法(例如居中和缩放)。您还可以使用以下代码:
library(caret)
# Assuming goal class is column 10
preObj <- preProcess(data[, -10], method=c("center", "scale"))
newData <- predict(preObj, data[, -10])
答案 4 :(得分:15)
当我使用Dason所说的解决方案时,我没有得到数据帧,而是得到了一个数字向量(我的df的缩放值)。
如果有人遇到同样的问题,你必须在代码中添加as.data.frame(),如下所示:
df.scaled <- as.data.frame(scale(df))
我希望这对有同样问题的人有用!
答案 5 :(得分:12)
您还可以使用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)/ range)
n4 - 零最小值((x-min)/范围)的单位化
n5-范围内的归一化&lt; -1,1&gt; ((X-平均值)/ MAX(ABS(X-平均值)))
n5a-范围内的位置归一化&lt; -1,1&gt; ((X-中值)/ MAX(ABS(X-中值)))
n6 - 商变换(x / sd)
n6a - 位置商变换(x / mad)
n7 - 商变换(x /范围)
n8 - 商变换(x / max)
n9 - 商变换(x / mean)
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))
正常化
“column” - 按变量标准化,“行” - 按对象标准化
答案 6 :(得分:7)
使用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
由reprex package(v0.2.0)创建于2018-04-24。
答案 7 :(得分:7)
同样,即使这是一个古老的问题,也非常重要!而且我发现了一种无需某些程序包即可对某些列进行规范化的简单方法:
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 :(得分:3)
缩放可用于完整数据框和特定列。 对于特定列,可以使用以下代码:
trainingSet <- scale(trainingSet)
完整数据框
{{1}}
答案 9 :(得分:1)
在我碰巧找到这个帖子之前,我遇到了同样的问题。我有用户相关的列类型,因此我编写了一个for
循环,通过它们获取所需的列scale
&#39; d。可能有更好的方法来做到这一点,但这解决了问题就好了:
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 1
矩阵,这通常不是您想要的data.frame
。
答案 10 :(得分:1)
dplyr
程序包具有两个执行此操作的功能。
> require(dplyr)
要变异数据表的 specific 列,可以使用函数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
答案 11 :(得分:1)
@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))
答案 12 :(得分:1)
collapse 软件包提供了最快的缩放功能-使用Welfords在线算法在C ++中实现:
dat <- data.frame(x = rnorm(1e6, 30, .2),
y = runif(1e6, 3, 5),
z = runif(1e6, 10, 20))
library(collapse)
library(microbenchmark)
microbenchmark(fscale(dat), scale(dat))
Unit: milliseconds
expr min lq mean median uq max neval cld
fscale(dat) 27.86456 29.5864 38.96896 30.80421 43.79045 313.5729 100 a
scale(dat) 357.07130 391.0914 489.93546 416.33626 625.38561 793.2243 100 b
此外:fscale
是S3的矢量,矩阵和数据帧通用名称,还支持分组和/或加权缩放操作,以及缩放到任意均值和标准差。
答案 13 :(得分:0)
BBMisc软件包中的normalize函数对我来说是正确的工具,因为它可以处理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的colmuns:
> 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)