如何在R中使用Box-Cox功率变换

ded*_*ede 23 r transformation

我需要将一些数据转换为"正常形状",并且我读到Box-Cox可以识别用于转换数据的指数.

对于我的理解

car::boxCoxVariable(y)
Run Code Online (Sandbox Code Playgroud)

用于线性模型中的响应变量,和

MASS::boxcox(object)
Run Code Online (Sandbox Code Playgroud)

对于公式或拟合的模型对象.因此,因为我的数据是数据帧的变量,所以我发现我可以使用的唯一函数是:

car::powerTransform(dataframe$variable, family="bcPower")
Run Code Online (Sandbox Code Playgroud)

那是对的吗?或者我错过了什么?

第二个问题是关于我获得之后要做什么

Estimated transformation parameters
dataframe$variable
0.6394806
Run Code Online (Sandbox Code Playgroud)

我应该简单地将变量乘以这个值吗?我这样做了:

aaa = 0.6394806
dataframe$variable2 = (dataframe$variable)*aaa
Run Code Online (Sandbox Code Playgroud)

然后我运行shapiro-wilks测试的正常性,但我的数据似乎不遵循正态分布:

shapiro.test(dataframe$variable2)
data:  dataframe$variable2
W = 0.97508, p-value < 2.2e-16
Run Code Online (Sandbox Code Playgroud)

mle*_*gge 27

Box和Cox(1964)提出了一系列变换,旨在减少线性模型中误差的非正态性.事实证明,在这样做时,它通常也会降低非线性.

以下是对原始工作以及自此以来所做的所有工作的一个很好的总结:http://www.ime.usp.br/~abe/lista/pdfm9cJKUmFZp.pdf

但是,您会注意到,控制λ功率变换选择的对数似然函数取决于基础模型的残差平方(SO上没有LaTeX - 参见参考),因此不能应用任何变换没有模特.

典型应用如下:

library(MASS)

# generate some data
set.seed(1)
n <- 100
x <- runif(n, 1, 5)
y <- x^3 + rnorm(n)

# run a linear model
m <- lm(y ~ x)

# run the box-cox transformation
bc <- boxcox(y ~ x)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

(lambda <- bc$x[which.max(bc$y)])
[1] 0.4242424

powerTransform <- function(y, lambda1, lambda2 = NULL, method = "boxcox") {

  boxcoxTrans <- function(x, lam1, lam2 = NULL) {

    # if we set lambda2 to zero, it becomes the one parameter transformation
    lam2 <- ifelse(is.null(lam2), 0, lam2)

    if (lam1 == 0L) {
      log(y + lam2)
    } else {
      (((y + lam2)^lam1) - 1) / lam1
    }
  }

  switch(method
         , boxcox = boxcoxTrans(y, lambda1, lambda2)
         , tukey = y^lambda1
  )
}


# re-run with transformation
mnew <- lm(powerTransform(y, lambda) ~ x)

# QQ-plot
op <- par(pty = "s", mfrow = c(1, 2))
qqnorm(m$residuals); qqline(m$residuals)
qqnorm(mnew$residuals); qqline(mnew$residuals)
par(op)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

正如您所看到的,这不是灵丹妙药 - 只有一些数据可以有效转换(通常λ小于-2或大于2是一个不应该使用该方法的标志).与任何统计方法一样,在实施前请谨慎使用.

要使用两个参数Box-Cox转换,请使用geoR包来查找lambdas:

library("geoR")
bc2 <- boxcoxfit(x, y, lambda2 = TRUE)

lambda1 <- bc2$lambda[1]
lambda2 <- bc2$lambda[2]
Run Code Online (Sandbox Code Playgroud)

编辑:正如@ Yui-Shiuan所指出的Tukey和Box-Cox实施的融合.


Yun*_*uan 13

根据Box Box中的Box-cox变换公式,George EP; 考克斯,DR(1964年)."对转换的分析",我认为mlegge的帖子可能需要稍加编辑.转换后的y应该是(y ^(lambda)-1)/ lambda而不是y ^(lambda).(实际上,y ^(lambda)被称为Tukey变换,这是另一个不同的变换公式.)
因此,代码应该是:

(trans <- bc$x[which.max(bc$y)])
[1] 0.4242424
# re-run with transformation
mnew <- lm(((y^trans-1)/trans) ~ x) # Instead of mnew <- lm(y^trans ~ x) 
Run Code Online (Sandbox Code Playgroud)

更多信息

  • 通过boxcox()在R中正确实现Box-Cox转换公式:https://www.r-bloggers.com/on-box-cox-transform-in-regression-models/

  • Box-Cox变换与Tukey变换的比较.http://onlinestatbook.com/2/transformations/box-cox.html

  • 人们还可以在维基百科上找到Box-Cox转换公式:en.wikipedia.org/wiki/Power_transform#Box.E2.80.93Cox_transformation

如果我误解了,请纠正我.


小智 5

如果我只想传输响应变量 y 而不是指定了 x 的线性模型,例如我想传输/规范化数据列表,我可以将 x 取 1,然后该对象将成为线性模型:

library(MASS)
y = rf(500,30,30)
hist(y,breaks = 12)
result = boxcox(y~1, lambda = seq(-5,5,0.5))
mylambda = result$x[which.max(result$y)]
mylambda
y2 = (y^mylambda-1)/mylambda
hist(y2)
Run Code Online (Sandbox Code Playgroud)