backtransform `scale()` for plotting

前端 未结 8 2282
别那么骄傲
别那么骄傲 2020-11-28 07:05

I have a explanatory variable that is centered using scale() that is used to predict a response variable:

d <- data.frame(
  x=runif(100),
           


        
8条回答
  •  孤独总比滥情好
    2020-11-28 07:32

    I am late to the party. But here is a useful tool to scale/unscale data in array format.

    Example:

    > (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
    

    Function 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)
    }
    

    Note: data.frames are not support yet.

提交回复
热议问题