我有一个使用scale()
居中的解释变量,用于预测响应变量:
d <- data.frame(
x=runif(100),
y=rnorm(100)
)
d <- within(d, s.x <- scale(x))
m1 <- lm(y~s.x, data=d)
我想绘制预测值,但使用x
的原始比例而不是中心比例。有没有办法进行反向转换或反向比例s.x
?
谢谢!
答案 0 :(得分:50)
看看:
attributes(d$s.x)
您可以使用属性进行取消缩放:
d$s.x * attr(d$s.x, 'scaled:scale') + attr(d$s.x, 'scaled:center')
例如:
> x <- 1:10
> s.x <- scale(x)
> s.x
[,1]
[1,] -1.4863011
[2,] -1.1560120
[3,] -0.8257228
[4,] -0.4954337
[5,] -0.1651446
[6,] 0.1651446
[7,] 0.4954337
[8,] 0.8257228
[9,] 1.1560120
[10,] 1.4863011
attr(,"scaled:center")
[1] 5.5
attr(,"scaled:scale")
[1] 3.02765
> s.x * attr(s.x, 'scaled:scale') + attr(s.x, 'scaled:center')
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
[6,] 6
[7,] 7
[8,] 8
[9,] 9
[10,] 10
attr(,"scaled:center")
[1] 5.5
attr(,"scaled:scale")
[1] 3.02765
答案 1 :(得分:12)
对于数据框或矩阵:
set.seed(1)
x = matrix(sample(1:12), ncol= 3)
xs = scale(x, center = TRUE, scale = TRUE)
x.orig = t(apply(xs, 1, function(r)r*attr(xs,'scaled:scale') + attr(xs, 'scaled:center')))
print(x)
[,1] [,2] [,3]
[1,] 4 2 3
[2,] 5 7 1
[3,] 6 10 11
[4,] 9 12 8
print(x.orig)
[,1] [,2] [,3]
[1,] 4 2 3
[2,] 5 7 1
[3,] 6 10 11
[4,] 9 12 8
使用identical()
等功能时要小心:
print(x - x.orig)
[,1] [,2] [,3]
[1,] 0 0 0.000000e+00
[2,] 0 0 8.881784e-16
[3,] 0 0 0.000000e+00
[4,] 0 0 0.000000e+00
identical(x, x.orig)
# FALSE
答案 2 :(得分:6)
我觉得这应该是一个合适的功能,这是我的尝试:
var jun = moment("2014-06-01T12:00:00Z");
var dec = moment("2014-12-01T12:00:00Z");
jun.tz('America/Los_Angeles').format('ha z'); // 5am PDT **I get 7am**
dec.tz('America/Los_Angeles').format('ha z'); // 4am PST **I get 6am**
答案 3 :(得分:3)
TL; DR:
unscaled_vals <- xs + attr(xs, 'scaled:scale') + attr(xs, 'scaled:center')
xs
是由scale(x)
对于那些试图对此有所了解的人:
R如何扩展:
scale
功能默认执行缩放和居中。
centering
。 默认情况下,通过从每个值中减去所有!is.na
输入值的平均值来实现居中:
data - mean(data, rm.na = T)
通过以下方式实现缩放:
sqrt( ( sum(x^2) ) / n - 1)
其中x
是要扩展的所有!is.na
值的集合,n
= length(x)
。
重要的是,当center =T
中的scale
时,x
不是原始数据集,而是已经居中数据。
因此,如果center = T
(默认值),缩放功能真正计算:
sqrt( ( sum( (data - mean(data, rm.na = T))^2) ) / n - 1)
center = T
时]这与采用标准偏差相同:sd(data)
。如何取消缩放:
解释:
首先乘以比例因子:
y = x * sqrt( ( sum( (x - mean(x , na.rm = T))^2) ) / (length(x) - 1))
然后加回平均值:
y + mean(x , na.rm = T)
显然,你需要知道这个手动方法的原始数据集的平均值真正是有用的,但我把它放在这里是为了概念。
幸运的是,正如之前的答案所示,“居中”值(即 mean )位于scale
对象的属性中,因此这种方法可以简化为:
如何做R :
unscaled_vals <- xs + attr(xs, 'scaled:scale') + attr(xs, 'scaled:center')
xs
是由scale(x)
创建的缩放对象。答案 4 :(得分:1)
我遇到了这个问题,我想我找到了一个使用线性代数的简单解决方案。
# create matrix like object
a <- rnorm(1000,5,2)
b <- rnorm(1000,7,5)
df <- cbind(a,b)
# get center and scaling values
mean <- apply(df, 2, mean)
sd <- apply(df, 2, sd)
# scale data
s.df <- scale(df, center = mean, scale = sd)
#unscale data with linear algebra
us.df <- t((t(s.df) * sd) + mean)
答案 5 :(得分:1)
古老的问题,但是为什么不这样做呢?
plot(d$x, predict(m1, d))
与手动使用缩放对象中的属性相比,DMwR具有一种简便的方法:unscale
。它是这样的:
d <- data.frame(
x=runif(100)
)
d$y <- 17 + d$x * 12
s.x <- scale(d$x)
m1 <- lm(d$y~s.x)
library(DMwR)
unsc.x <- unscale(d$x, s.x)
plot(unsc.x, predict(m1, d))
重要的是,unscale
的第二个自变量需要具有'scaled:scale'
和'scaled:center'
的属性
答案 6 :(得分:0)
我迟到了。但这是一个有用的工具,可以按数组格式缩放/取消缩放数据。
示例:
> (data <- array(1:8, c(2, 4))) # create data
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
> obj <- Scale(data) # create object
> (data_scaled <- obj$scale(data)) # scale data
[,1] [,2] [,3] [,4]
[1,] -0.7071068 -0.7071068 -0.7071068 -0.7071068
[2,] 0.7071068 0.7071068 0.7071068 0.7071068
> (obj$unscale(data_scaled)) # unscale scaled data
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
## scale or unscale another dataset
## using the same mean/sd parameters
> (data2 <- array(seq(1, 24, 2), c(3, 4))) # create demo data
[,1] [,2] [,3] [,4]
[1,] 1 7 13 19
[2,] 3 9 15 21
[3,] 5 11 17 23
> (data2_scaled <- obj$scale(data2)) # scale data
[,1] [,2] [,3] [,4]
[1,] -0.7071068 4.949747 10.60660 16.26346
[2,] 2.1213203 7.778175 13.43503 19.09188
[3,] 4.9497475 10.606602 16.26346 21.92031
> (obj$unscale(data2_scaled)) # unscale scaled data
[,1] [,2] [,3] [,4]
[1,] 1 7 13 19
[2,] 3 9 15 21
[3,] 5 11 17 23
功能 Scale()
:
Scale <- function(data, margin=2, center=TRUE, scale=TRUE){
stopifnot(is.array(data), is.numeric(data),
any(mode(margin) %in% c("integer", "numeric")),
length(margin) < length(dim(data)),
max(margin) <= length(dim(data)),
min(margin) >= 1,
!any(duplicated(margin)),
is.logical(center), length(center)==1,
is.logical(scale), length(scale)==1,
!(isFALSE(center) && isFALSE(scale)))
margin <- as.integer(margin)
m <- if(center) apply(data, 2, mean, na.rm=TRUE) else NULL
s <- if(scale) apply(data, 2, sd, na.rm=TRUE) else NULL
ldim <- length(dim(data))
cdim <- dim(data)[margin]
data <- NULL # don't store the data
Scale <- function(data){
stopifnot(is.array(data), is.numeric(data),
length(dim(data)) == ldim,
dim(data)[margin] == cdim)
if(center)
data <- sweep(data, margin, m, `-`)
if(scale)
data <- sweep(data, margin, s, `/`)
data
}
Unscale <- function(data){
stopifnot(is.array(data), is.numeric(data),
length(dim(data)) == ldim,
dim(data)[margin] == cdim)
if(scale)
data <- sweep(data, margin, s, `*`)
if(center)
data <- sweep(data, margin, m, `+`)
data
}
list(scale=Scale, unscale=Unscale, mean=m, sd=s)
}
注意:
目前尚不支持data.frame
。
答案 7 :(得分:0)
只是受Fermando的回答启发,但是用更少的代码扩展了行:
set.seed(1)
x = matrix(sample(1:12), ncol= 3)
xs = scale(x, center = TRUE, scale = TRUE)
center <- attr(xs,"scaled:center")
scale <- attr(xs,"scaled:scale")
x.orig <- t(t(xs) * scale + center) # code is less here
print(x)
[1,] 9 2 6
[2,] 4 5 11
[3,] 7 3 12
[4,] 1 8 10
print(x.orig)
[1,] 9 2 6
[2,] 4 5 11
[3,] 7 3 12
[4,] 1 8 10
attr(,"scaled:center")
[1] 5.25 4.50 9.75
attr(,"scaled:scale")
[1] 3.50 2.65 2.63
答案 8 :(得分:0)
我发现反转 scale()
函数的一种简单方法是调用两次 scale()
函数:
X_scaled <- scale(X,center=TRUE,scale=TRUE)
X_reversed <- scale(X_scaled,center=FALSE,scale=1/attr(X_scaled,'scaled:scale'))
X_reversed <- scale(X_reversed,center=-attr(X_scaled,'scaled:center'),scale=FALSE)
如果您不介意在函数的参数内调用函数(我确实介意),您可能会得到以下解决方案:
X_scaled <- scale(X,center=TRUE,scale=TRUE)
X_reversed <- scale(scale(X_scaled,center=FALSE,scale=1/attr(X_scaled,'scaled:scale')),
center=-attr(X_scaled,'scaled:center'),scale=FALSE)