Обсуждаемое здесь преобразование мощности Йео-Джонсона обладает превосходными свойствами, разработанными для обработки нулей и негативов, в то же время опираясь на сильные стороны преобразования мощности Бокс-Кокса. Это то, к чему я обычно обращаюсь, когда имею дело с нулями или отрицательными данными.
Вот краткое изложение преобразований с плюсами / минусами, чтобы проиллюстрировать, почему Йео-Джонсон предпочтительнее.
Журнал
Плюсы: хорошо с положительными данными.
Минусы: не обрабатывает нули.
> log(0)
[1] -Inf
Log Plus 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
Box Cox
Код 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