Розглянута тут трансформація потужності Йо-Джонсона має чудові властивості, призначені для обробки нулів і негативів, будуючи при цьому сильні перетворення потужності Box Cox. Це те, до чого я зазвичай займаюся, коли маю справу з нулями або негативними даними.
Ось підсумок перетворень із плюсами / мінусами, щоб проілюструвати, чому Йе-Джонсон є кращим.
Журнал
Плюси: добре справляється з позитивними даними.
Мінуси: не обробляє нулі.
> log(0)
[1] -Inf
Журнал плюс 1
Плюси: Зсув плюс 1 додає можливість обробляти нулі на додаток до позитивних даних.
Мінуси: помилки з негативними даними
> log1p(-1)
[1] -Inf
> log1p(-2)
[1] NaN
Warning message:
In log1p(-2) : NaNs produced
Квадратний корінь
Плюси: використовується силова трансформація, яка може обробляти нулі та позитивні дані.
Мінуси: помилки з негативними даними
> sqrt(-1)
[1] NaN
Warning message:
In sqrt(-1) : NaNs produced
Кокс Кокс
R код:
box_cox <- function(x, lambda) {
eps <- 0.00001
if (abs(lambda) < eps)
log(x)
else
(x ^ lambda - 1) / lambda
}
Плюси: вмикає масштабовані силові перетворення
Мінуси: страждає від проблем із нулями та негативами (тобто може обробляти лише позитивні дані.
> box_cox(0, lambda = 0)
[1] -Inf
> box_cox(0, lambda = -0.5)
[1] -Inf
> box_cox(-1, lambda = 0.5)
[1] NaN
Єо Джонсон
R код:
yeo_johnson <- function(x, lambda) {
eps <- .000001
not_neg <- which(x >= 0)
is_neg <- which(x < 0)
not_neg_trans <- function(x, lambda) {
if (abs(lambda) < eps) log(x + 1)
else ((x + 1) ^ lambda - 1) / lambda
}
neg_trans <- function(x, lambda) {
if (abs(lambda - 2) < eps) - log(-x + 1)
else - ((-x + 1) ^ (2 - lambda) - 1) / (2 - lambda)
}
x[not_neg] <- not_neg_trans(x[not_neg], lambda)
x[is_neg] <- neg_trans(x[is_neg], lambda)
return(x)
}
Плюси: може обробляти позитивні, нульові та негативні дані.
Мінуси: жодного, що я можу придумати. Властивості дуже схожі на Box-Cox, але можуть обробляти нульові та негативні дані.
> yeo_johnson(0, lambda = 0)
[1] 0
> yeo_johnson(0, lambda = -0.5)
[1] 0
> yeo_johnson(-1, lambda = 0.5)
[1] -1.218951