R标准化数据框中的数字变量,同时保留因子变量

时间:2018-02-05 23:26:09

标签: r standardized

我在R中加载了一个数据帧(dcc),我已经缩小到完整的情况。

str(dcc)

'data.frame':   41715 obs. of  9 variables:
 $ XCoord                  : num  661382 661412 661442 661472 661502 ...
 $ YCoord                  : num  648092 648092 648092 648092 648092 ...
 $ OBJECTID                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ POINTID                 : int  1 2 3 4 5 6 7 8 9 10 ...
 $ GRID_CODE               : int  0 0 0 0 0 0 0 0 0 0 ...
 $ APPL_COST_DIST_RIV_COAST: num  21350 21674 22185 22748 23448 ...
 $ APPL_DEM30              : int  785 793 792 769 765 777 784 789 781 751 ...
 $ APPL_DEM30_SLOPE        : num  19.7 13.3 18.6 23.2 21 ...
 $ APPL_SITE_NONSITE       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...

我想通过减去平均值并除以标准差来标准化数值和整数变量。当我应用以下代码时,我无意中从数据帧中删除了因子变量APPL_SITE_NONSITE:

ind <- sapply(dcc, is.numeric)
dcc.s<-sapply(dcc[,ind], function(x) (x-mean(x))/sd(x))
dcc.s<-data.frame(dcc.s)

如果我没有弄错,那就是因为该变量的ind = FALSE。看起来我需要一些for循环和if / else语句的组合来标准化数值变量并保留factor因子变量。我尝试过多种排列,但不断出错。例如,以下代码:

dcc.s <- for (i in 1:ncol(dcc)){ sapply(dcc[,i],
if (is.numeric(dcc[,i])==TRUE) {
function(x) (x-mean(x))/sd(x) }
 else {dcc[,i]})
}

返回错误:

match.fun(FUN)出错:   c(&#34;&#39; if(is.numeric(dcc [,i])== TRUE){&#39;不是函数,字符或符号&#34;,&#34;&#39 ; function(x)(x - mean(x))/ sd(x)&#39;不是函数,字符或符号&#34;,&#34;&#39;} else {&#39; is不是功能,角色或符号&#34;,&#34;&#39; dcc [,i]&#39;不是功能,角色或符号&#34;,&#34;&#39;}& #39;不是函数,字符或符号&#34;)

也许这是一个简单的格式错误或错位的括号,但我完全卡住了。如果有更优雅的方式,我对其他方法持开放态度。任何帮助将非常感激。

3 个答案:

答案 0 :(得分:3)

您需要使用rapply代替sapply

set.seed(1)
> df=data.frame(A=rnorm(10),b=1:10,C=as.factor(rep(1:2,5)))
> str(df)
'data.frame':   10 obs. of  3 variables:
 $ A: num  -0.626 0.184 -0.836 1.595 0.33 ...
 $ b: int  1 2 3 4 5 6 7 8 9 10
 $ C: Factor w/ 2 levels "1","2": 1 2 1 2 1 2 1 2 1 2

您需要使用的代码:

> D=rapply(df,scale,c("numeric","integer"),how="replace")
> D
             A          b C
1  -0.97190653 -1.4863011 1
2   0.06589991 -1.1560120 2
3  -1.23987805 -0.8257228 1
4   1.87433300 -0.4954337 2
5   0.25276523 -0.1651446 1
6  -1.22045645  0.1651446 2
7   0.45507643  0.4954337 1
8   0.77649606  0.8257228 2
9   0.56826358  1.1560120 1
10 -0.56059319  1.4863011 2
> str(D)
'data.frame':   10 obs. of  3 variables:
 $ A: num [1:10, 1] -0.9719 0.0659 -1.2399 1.8743 0.2528 ...
  ..- attr(*, "scaled:center")= num 0.132
  ..- attr(*, "scaled:scale")= num 0.781
 $ b: num [1:10, 1] -1.486 -1.156 -0.826 -0.495 -0.165 ...
  ..- attr(*, "scaled:center")= num 5.5
  ..- attr(*, "scaled:scale")= num 3.03
 $ C: Factor w/ 2 levels "1","2": 1 2 1 2 1 2 1 2 1 2
> 

答案 1 :(得分:2)

ind <- sapply(dcc, is.numeric)
dcc.s <- as.data.frame(lapply(dcc[,ind], function(x) (x-mean(x))/sd(x)))
dcc.s <- cbind(dcc, dcc.s)

如果您不需要“旧”数据框,也可以

ind <- sapply(dcc, is.numeric)
dcc[,ind] <- vapply(dcc[,ind], function(x) (x-mean(x))/sd(x))

答案 2 :(得分:1)

以下是var x = { "foo": { "foo (e.g. bar)": { "foo (e.g. bar)2": { "foo (e.g. bar)3" : { "foo1": "bar1" } } } }, "a": "b" }; console.log('INPUT',JSON.stringify(x, null, ' ')); var y = deepTransformKeys(x); console.log('---------------------------'); console.log('OUTPUT', JSON.stringify(y, null, ' ')); dplyr解决方案:

scale

请注意,require(dplyr); df %>% mutate_if(is.numeric, scale); # a runif(20) rnorm(20) #1 y 0.5783877 -0.004177104 #2 n -0.2344854 -0.866626472 #3 m 1.5629961 1.526857969 #4 h 0.9648646 -1.557975547 #5 u -0.7212756 0.533400304 #6 u 1.4753675 -0.072289864 #7 b 0.5346870 -0.464299111 #8 l -0.4287559 0.426600473 #9 m -1.2050841 -0.880135405 #10 h -0.6150410 -0.040636433 #11 r 1.3768249 -0.719785950 #12 a -1.3929511 0.083010969 #13 a -0.4422665 0.385574213 #14 l -0.7719473 -0.934716525 #15 m 1.4483803 0.131974911 #16 k 0.6291919 2.598581195 #17 k -1.0356817 -1.018890381 #18 s -1.0960083 1.560216350 #19 y -0.8826702 -0.367821579 #20 v 0.2554671 -0.318862011 将与scale(x)相同;如果您想根据不同的指标进行扩展(例如,基于中位数和MAD的强大/修改的Z得分),您可以使用(x - mean(x)) / sd(x)进行扩展。

样本数据

sweep