58

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ますか?

ありがとう!

4

9 に答える 9

69

を見てみましょう:

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
于 2012-04-23T20:27:45.177 に答える
16

データフレームまたはマトリックスの場合:

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
于 2015-03-12T01:29:19.817 に答える
9

私はこれが適切な機能であるべきだと感じました、これが私の試みでした:

#' Reverse a scale
#'
#' Computes x = sz+c, which is the inverse of z = (x - c)/s 
#' provided by the \code{scale} function.
#' 
#' @param z a numeric matrix(like) object
#' @param center either NULL or a numeric vector of length equal to the number of columns of z  
#' @param scale  either NULL or a a numeric vector of length equal to the number of columns of z
#'
#' @seealso \code{\link{scale}}
#'  mtcs <- scale(mtcars)
#'  
#'  all.equal(
#'    unscale(mtcs), 
#'    as.matrix(mtcars), 
#'    check.attributes=FALSE
#'  )
#'  
#' @export
unscale <- function(z, center = attr(z, "scaled:center"), scale = attr(z, "scaled:scale")) {
  if(!is.null(scale))  z <- sweep(z, 2, scale, `*`)
  if(!is.null(center)) z <- sweep(z, 2, center, `+`)
  structure(z,
    "scaled:center"   = NULL,
    "scaled:scale"    = NULL,
    "unscaled:center" = center,
    "unscaled:scale"  = scale
  )
}
于 2017-10-19T22:58:08.707 に答える
6

tl; dr:

unscaled_vals <- xs + attr(xs, 'scaled:scale') + attr(xs, 'scaled:center')
  • xsによって作成されたスケーリングされたオブジェクトはどこですかscale(x)

これについて少し理解しようとしている人のためだけに:

Rのスケーリング方法

このscale関数は、デフォルトでスケーリングとセンタリングの両方を実行します。

  • 2つのうち、関数がcentering最初に実行されます。

センタリングは、デフォルトで!is.na、各値からすべての入力値の平均を引くことによって実現されます。

data - mean(data, rm.na = T)

スケーリングは、次の方法で実現されます。

sqrt( ( sum(x^2) ) / n - 1)

ここで、はスケーリングするxすべての値のセットであり、 =です。!is.nanlength(x)

  • ただし、重要なのは、にある場合center =T、元のデータセットscalexはなく、すでに中央に配置されているデータです。

    したがって、center = T(デフォルト)の場合、スケーリング関数は実際に次のように計算しています。

     sqrt( ( sum( (data - mean(data, rm.na = T))^2) ) / n - 1)
    
    • 注:[いつcenter = T]これは標準偏差を取るのと同じです:sd(data)

スケールを解除する方法

説明

  1. 最初にスケーリング係数を掛けます:

    y = x * sqrt( ( sum( (x - mean(x , na.rm = T))^2) ) / (length(x) - 1))
    
  2. 次に、平均を追加します。

    y + mean(x , na.rm = T)
    

明らかに、この手動アプローチが本当に役立つためには、元のデータセットの平均を知る必要がありますが、概念的な目的でここに配置します。

幸い、以前の回答が示しているように、「センタリング」値(つまり、平均)はscaleオブジェクトの属性にあるため、このアプローチは次のように簡略化できます。

Rで行う方法

unscaled_vals <- xs + attr(xs, 'scaled:scale') + attr(xs, 'scaled:center')
  • ここで、xsはによって作成されたスケーリングされたオブジェクトですscale(x)
于 2018-05-24T20:29:25.227 に答える
4

私はこの問題に遭遇し、線形代数を使用したより簡単な解決策を見つけたと思います。

# 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)
于 2019-03-05T16:11:24.827 に答える
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))

重要なのは、の2番目の引数には、とunscaleの属性を持つものが必要です。'scaled:scale''scaled:center'

于 2019-03-18T21:47:22.153 に答える
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 sはまだサポートされていません。

于 2020-09-04T22:09:47.953 に答える
0

フェルマンドの答えに触発されただけですが、コードが少ない非スケーリング行:

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
于 2020-10-14T18:34:46.707 に答える
0

関数を元に戻す簡単な方法は、scale()関数を2回呼び出すこと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)

于 2021-03-20T15:00:12.427 に答える