数据处理时经常需要做各种处理,如标准化和归一化,在R里面可以借助scale
函数来轻松完成。默认情况下,该函数做的事情可以用下面的公式概括:
其中 x 是原始数据点,μ 是数据的均值,σ 是数据的标准差,z 是标准化后的值。
vec <- 1:5
scale(vec)
[,1]
[1,] -1.2649111
[2,] -0.6324555
[3,] 0.0000000
[4,] 0.6324555
[5,] 1.2649111
attr(,"scaled:center")
[1] 3
attr(,"scaled:scale")
[1] 1.581139
可知,该函数默认参数(center=TRUE
,scale=TRUE
)条件下对数据做了标准正态化处理,这也是通常情况下的需求。虽然该函数很简单,但做的事情却不止于此。通过调整这两个参数也可以单独只做center
,或者scale
,即只做公式的上面或者下面。
scale(vec, scale=F)
[,1]
[1,] -2
[2,] -1
[3,] 0
[4,] 1
[5,] 2
attr(,"scaled:center")
[1] 3
只做center
很容易理解,即每一个值都减去均值,也就是处理后的数据均值为0。
scale(vec, center=F)
[,1]
[1,] 0.2696799
[2,] 0.5393599
[3,] 0.8090398
[4,] 1.0787198
[5,] 1.3483997
attr(,"scaled:scale")
[1] 3.708099
当只做scale
时,结果就有点不同寻常,为什么是每个数除以均方根而不是标准差呢?先来看看两者的计算公式:
回顾上面的公式可知,标准差可以拆分成两部分:中心化和均方根。事实上,scale
函数的代码实现也正是如此,先做中心化,然后计算均方根,现在再回头看上面的代码不同组合的结果就理所当然了。
当然,scale
的参数不仅可以是默认的布尔值,也可以是具体的数字,这也增加了函数的可能性,让函数可以做更多的事情,比如下面的代码:
scale(vec, center=3)
[,1]
[1,] -1.2649111
[2,] -0.6324555
[3,] 0.0000000
[4,] 0.6324555
[5,] 1.2649111
attr(,"scaled:center")
[1] 3
attr(,"scaled:scale")
[1] 1.581139
向量vec
的均值为3,如果将center
参数设置为3,则其结果与默认参数一致,这样可以说明scale
函数的代码实现是先做中心化,然后计算均方根。
这样一来scale
函数可就很灵活了,虽然很简单,却可以省却很多时间,比如做个归一化也很方便:
# 映射到[ 0, 1]
scale(vec, center=min(vec), scale=max(vec)-min(vec))
[,1]
[1,] 0.00
[2,] 0.25
[3,] 0.50
[4,] 0.75
[5,] 1.00
attr(,"scaled:center")
[1] 1
attr(,"scaled:scale")
[1] 4
# 比如映射到[ -1, 1]
scale(vec, scale=max(vec)-min(vec))
[,1]
[1,] -0.50
[2,] -0.25
[3,] 0.00
[4,] 0.25
[5,] 0.50
attr(,"scaled:center")
[1] 3
attr(,"scaled:scale")
[1] 4
用工具,精髓在于一句话:知其道,用奇妙!这样站在巨人的肩膀上仰望才不会一眼迷茫!与君共勉。