首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在R中使用Box&Cox幂变换

如何在R中使用Box&Cox幂变换
EN

Stack Overflow用户
提问于 2015-11-30 13:14:11
回答 4查看 167.5K关注 0票数 40

我需要将一些数据转换成“正常形状”,我读到了Box-Cox可以识别用于转换数据的指数。

因为我所理解的

代码语言:javascript
复制
car::boxCoxVariable(y)

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

代码语言:javascript
复制
MASS::boxcox(object)

为一个公式或合适的模型对象。因此,因为我的数据是dataframe的变量,所以我可以使用的唯一函数是:

代码语言:javascript
复制
car::powerTransform(dataframe$variable, family="bcPower")

对吗?还是我漏掉了什么?

第二个问题是在我获得

代码语言:javascript
复制
Estimated transformation parameters
dataframe$variable
0.6394806

我应该把这个变量乘以这个值吗?我这样做了:

代码语言:javascript
复制
aaa = 0.6394806
dataframe$variable2 = (dataframe$variable)*aaa

然后我做了夏皮罗-威尔克斯的正常度测试,但我的数据似乎并没有遵循正态分布:

代码语言:javascript
复制
shapiro.test(dataframe$variable2)
data:  dataframe$variable2
W = 0.97508, p-value < 2.2e-16
EN

回答 4

Stack Overflow用户

发布于 2015-11-30 15:25:31

Box和Cox (1964)提出了一个变换族,旨在减少线性模型中误差的非正态性。结果表明,在这样做时,它往往也减少了非线性。

下面是对原始工作和自:http://www.ime.usp.br/~abe/lista/pdfm9cJKUmFZp.pdf之后所做的所有工作的很好的总结

但是,您会注意到,用于选择lambda幂变换的log-似然函数依赖于底层模型的残差平方和(在SO --参见引用上没有LaTeX ),因此没有模型就无法应用转换。

典型的应用程序如下:

代码语言:javascript
复制
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)

代码语言:javascript
复制
(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)

正如您所看到的,这不是一颗神奇的子弹--只有一些数据可以有效地转换(通常,小于-2或大于2的lambda是不应该使用该方法的一个标志)。与任何统计方法一样,在实现之前要谨慎使用。

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

代码语言:javascript
复制
library("geoR")
bc2 <- boxcoxfit(x, y, lambda2 = TRUE)

lambda1 <- bc2$lambda[1]
lambda2 <- bc2$lambda[2]

编辑:@Yui指出的Tukey和Box-Cox实现的合并。

票数 40
EN

Stack Overflow用户

发布于 2017-05-24 15:26:51

根据纸箱中的Box-cox变换公式,George E.P.;Cox,D.R.(1964)。“对转换的分析”,我认为mlegge的文章可能需要稍微转换y是( y^(lambda) -1)/lambda,而不是y^(Lambda)。(实际上,y^(Lambda)称为Tukey转换,这是另一个不同的转换公式)。

因此,代码应该是:

代码语言:javascript
复制
(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) 

更多信息

  • 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。

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

票数 22
EN

Stack Overflow用户

发布于 2020-06-08 21:52:41

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

代码语言:javascript
复制
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)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33999512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档