Как использовать трансформацию мощности Box-Cox в R

Мне нужно преобразовать некоторые данные в "нормальную форму", и я прочитал, что Box-Cox может идентифицировать экспонента для преобразования данных.

Для чего я понял

car::boxCoxVariable(y)

используется для переменных ответа в линейных моделях, а

MASS::boxcox(object)

для формулы или моделируемого объекта модели. Итак, поскольку мои данные являются переменной фрейма данных, единственная функция, которую я нашел, я мог бы использовать:

car::powerTransform(dataframe$variable, family="bcPower")

Это правильно? Или я что-то упускаю?

Второй вопрос: что делать после того, как я получу

Estimated transformation parameters
dataframe$variable
0.6394806

Должен ли я просто умножать переменную на это значение? Я сделал это:

aaa = 0.6394806
dataframe$variable2 = (dataframe$variable)*aaa

а затем я запускаю тест shapiro-wilks для нормальности, но опять же мои данные, похоже, не следуют нормальному распределению:

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

Ответы

Ответ 1

Box и Cox (1964) предложили семейство преобразований, призванных уменьшить не норму ошибок в линейной модели. В результате получается, что при этом он часто также снижает нелинейность.

Вот хорошее резюме оригинальной работы и всей работы, которая была сделана с тех пор: http://www.ime.usp.br/~abe/lista/pdfm9cJKUmFZp.pdf

Однако вы заметите, что функция логарифмического правдоподобия, определяющая выбор силового преобразования лямбда, зависит от остаточной суммы квадратов базовой модели (нет LaTeX на SO - см. ссылку), поэтому никакое преобразование может применяться без модели.

Типичное приложение выглядит следующим образом:

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)

введите описание изображения здесь

(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 - это знак, который вы не должны использовать метод). Как и любой статистический метод, используйте с осторожностью перед реализацией.

Чтобы использовать два параметра Box-Cox, используйте пакет geoR, чтобы найти lambdas:

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

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

РЕДАКТИРОВКА: Уплотнение реализации Туки и Box-Cox, как указано в @Yui-Shiuan, исправлено.

Ответ 2

В соответствии с формулой преобразования Box-cox в бумажной коробке George E. P.; Кокс, D.R. (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) 

Дополнительная информация

Пожалуйста, исправьте меня, если я его неправильно понял.