Геометрическое среднее: есть ли встроенный?
Я попытался найти встроенный для среднего геометрический, но не смог.
(Очевидно, что встроенный не собирается меня спасать во время работы в оболочке, и я не подозреваю о какой-либо разнице в точности; для скриптов я стараюсь использовать встроенные модули как можно чаще, (кумулятивное) усиление производительности часто заметно.
В случае, если нет одного (что я сомневаюсь в этом), здесь мой.
gm_mean = function(a){prod(a)^(1/length(a))}
Ответы
Ответ 1
Вот векторная, нулевая и NA-толерантная функция для вычисления геометрического среднего в R. Подробный расчет mean
с участием length(x)
необходим для случаев, когда x
содержит неположительные значения.
gm_mean = function(x, na.rm=TRUE){
exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
}
Спасибо @ben-bolker за то, что вы отметили прохождение na.rm
и @Gregor для обеспечения правильной работы.
Я думаю, что некоторые из комментариев связаны с ложной эквивалентностью значений NA
в данных и нулях. В приложении я имел в виду, что они одинаковы, но, конечно, это не так. Таким образом, если вы хотите включить опциональное распространение нулей и по-разному относиться к length(x)
в случае удаления NA
, это немного более длинная альтернатива вышеприведенной функции.
gm_mean = function(x, na.rm=TRUE, zero.propagate = FALSE){
if(any(x < 0, na.rm = TRUE)){
return(NaN)
}
if(zero.propagate){
if(any(x == 0, na.rm = TRUE)){
return(0)
}
exp(mean(log(x), na.rm = na.rm))
} else {
exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
}
}
Обратите внимание, что он также проверяет любые отрицательные значения и возвращает более информативное и соответствующее NaN
значение этого геометрического среднего для отрицательных значений (но для нулей). Спасибо комментаторам, которые остались в моем случае об этом.
Ответ 2
Нет, но есть несколько человек, которые написали один, например, здесь.
Другая возможность заключается в использовании этого:
exp(mean(log(x)))
Ответ 3
exp(mean(log(x)))
будет работать, если не будет 0 в x. Если это так, журнал будет создавать -Inf (-Infinite), который всегда приводит к среднему геометрическому значению 0.
Одним из решений является удаление значения -Inf перед вычислением среднего значения:
geo_mean <- function(data) {
log_data <- log(data)
gm <- exp(mean(log_data[is.finite(log_data)]))
return(gm)
}
Для этого вы можете использовать однострочный лайнер, но это означает, что в два раза не выполняется анализ журнала.
exp(mean(log(i[is.finite(log(i))])))
Ответ 4
вы можете использовать пакет psych
и вызвать функцию geometric.mean
в этом.
Ответ 5
Я использую именно то, что говорит Марк. Таким образом, даже при помощи вы можете использовать встроенную функцию mean
, вам не нужно определять ваши! Например, для вычисления геометрических средств данных для каждой группы $value:
exp(tapply(log(data$value), data$group, mean))
Ответ 6
Если в ваших данных отсутствуют значения, это не редкий случай.
вам нужно добавить еще один аргумент.
Вы можете попробовать следующие коды.
exp(mean(log(i[is.finite(log(i))]),na.rm=T))
Ответ 7
В пакете EnvStats есть функция для geoMean и geoSd
Ответ 8
Вот моя версия. Он имеет следующие особенности, которые отличают его от принятого в настоящее время ответа Пола МакМерди:
- Когда
na.rm == TRUE
, значения NA
игнорируются в знаменателе - следовательно, использование не пропущенных значений подсчитывает переменную values.count
в знаменателе вместо length(x)
. - При желании он различает значения
NaN
и общие значения NA
с параметром .rm
для каждого. По умолчанию NaN
являются "плохими", так же как отрицательные числа являются плохими, поэтому возвращается NaN
. Наличие двух параметров для обработки пропущенных значений, очевидно, не является идеальным, но способ, которым я установил значения по умолчанию для этих параметров и упорядочил case_when
выражении case_when
должен (мы надеемся) устранить возможность неожиданного поведения. - Моя версия включает в себя еще один необязательный параметр
eta
который обрабатывает нули. eta
умолчанию - NA_real_
, в этом случае нули учитываются в знаменателе, но не распространяются (аналог необязательного параметра zero.propagate = FALSE
в принятом ответе). Когда передается положительное число, eta
функционирует как искусственная константа, добавляемая к x
(но только в том случае, если x
содержит нули). Когда передается любое другое число (предположительно 0), нули распространяются так же, как если бы zero.propagate
был установлен равным TRUE
в принятом ответе.
Я уверен, что могут потребоваться твики (например, может быть лучше добавить eta
(учитывая, что eta
- положительное число), независимо от того, есть нули или нет). Я думал даже о том, чтобы функция динамически выбирала значение для eta
на основе x
но не добавляла дополнительной сложности.
suppressMessages(library(dplyr))
geomean <- function(x, na.rm = TRUE, nan.rm = FALSE, eta = NA_real_) {
nan.count <- is.nan(x) %>%
sum()
na.count <- is.na(x) %>%
sum()
value.count <- !is.na(x) %>%
sum()
case_when(
#Handle cases when there are negative values, all values are missing, or
#missing values are not tolerated.
(nan.count > 0 & !nan.rm) | any(x < 0, na.rm = TRUE) ~ NaN,
(na.count > 0 & !na.rm) | value.count == 0 ~ NA_real_,
#Handle cases when non-missing values are either all positive or all zero.
#In these cases the eta parameter is irrelevant and therefore ignored.
all(x > 0, na.rm = TRUE) ~ exp(mean(log(x), na.rm = TRUE)),
all(x == 0, na.rm = TRUE) ~ 0,
#All remaining cases are cases when there are a mix of positive and zero values.
#By default, we do not use an artificial constant or propagate zeros.
is.na(eta) ~ exp(sum(log(x[x > 0]), na.rm = TRUE) / value.count),
eta > 0 ~ exp(mean(log(x + eta), na.rm = TRUE)) - eta,
TRUE ~ 0 #only propagate zeroes when eta is set to 0 (or less than 0)
)
}