como utilizar a transformação de potência Box-Cox em R

Preciso de transformar alguns dados numa "forma normal" e li que a Box-Cox pode identificar o expoente a usar para transformar os dados.

pelo que eu entendi

car::boxCoxVariable(y)

é utilizado para variáveis de resposta em modelos lineares, e

MASS::boxcox(object)

para uma fórmula ou um objecto montado. Então, como meus dados são a variável de um dataframe, a única função que eu encontrei que eu poderia usar é:

car::powerTransform(dataframe$variable, family="bcPower")
Está correcto? Ou está a escapar-me alguma coisa?

A segunda questão é: sobre o que fazer depois de obter o

Estimated transformation parameters
dataframe$variable
0.6394806

devo simplesmente multiplicar a variável por este valor? Eu fiz isso.

aaa = 0.6394806
dataframe$variable2 = (dataframe$variable)*aaa
E depois faço o teste shapiro-wilks para a normalidade,mas, mais uma vez, os meus dados não parecem seguir uma distribuição normal.
shapiro.test(dataframe$variable2)
data:  dataframe$variable2
W = 0.97508, p-value < 2.2e-16
Author: Kasia Kulma, 2015-11-30

2 answers

Box e Cox (1964) sugeriram uma família de transformações concebidas para reduzir a nnormalidade dos erros num modelo linear. Acontece que ao fazer isso, muitas vezes reduz a não linearidade também.

Aqui está um belo resumo do trabalho original e de todo o trabalho que tem sido feito desde: http://www.ime.usp.br/~abe/lista / pdfm9cJKUmFZp.pdf

Você vai notar, no entanto, que a função de probabilidade log que rege a seleção do poder lambda a transformada é dependente da soma residual dos quadrados de um modelo subjacente (sem látex de SO -- see the reference), de modo que nenhuma transformação pode ser aplicada sem um modelo.

Uma aplicação típica é a seguinte:

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)

enter image description here

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

enter image description here

Como podem ver isto não é uma bala mágica -- apenas alguns dados podem ser efetivamente transformados (normalmente um lambda menor que -2 ou maior que 2 é um sinal de que não devem usar o método). Como com qualquer outro método estatístico, utilizar com precaução antes da implementação.

Para usar os dois parâmetros de transformação Box-Cox, use o pacote geoR para encontrar os lambdas:

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

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

EDITS: Conflation of Tukey and Box-Cox implementation as pointed out by @Yui-Shiuan fixed.

 19
Author: mlegge, 2017-06-02 14:48:55

De acordo com a fórmula de transformação Box-cox no papel Box,George E. P.; Cox,D. R.(1964). "An analysis of transformations" , I think millegge's post might need to be slightly edited.O y transformado deve ser y^(lambda) -1) / lambda em vez de y^(lambda). (na verdade, y^(lambda) é chamada transformação Tukey, que é outra fórmula de transformação distinta.) Então, o código deve ser:

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

Mais informação

Por favor, corrija-me se percebi mal.
 8
Author: Yun-Shiuan, 2017-05-24 15:48:10