기하 평균에 대한 내장을 찾으려고했지만 찾을 수 없었습니다.
(분명히 빌트인은 쉘에서 작업하는 동안 저를 절약 할 수 없으며 정확도에 차이가 있다고 생각하지 않습니다. 스크립트의 경우 빌트인을 가능한 한 자주 사용하려고합니다. 성능 향상은 종종 눈에 띄게 나타납니다.
(내가 의심하는) 하나가 없다면 여기 내 것입니다.
gm_mean = function(a){prod(a)^(1/length(a))}
기하 평균에 대한 내장을 찾으려고했지만 찾을 수 없었습니다.
(분명히 빌트인은 쉘에서 작업하는 동안 저를 절약 할 수 없으며 정확도에 차이가 있다고 생각하지 않습니다. 스크립트의 경우 빌트인을 가능한 한 자주 사용하려고합니다. 성능 향상은 종종 눈에 띄게 나타납니다.
(내가 의심하는) 하나가 없다면 여기 내 것입니다.
gm_mean = function(a){prod(a)^(1/length(a))}
답변:
다음은 R에서 기하 평균을 계산하기위한 벡터화 된 0 및 NA 허용 함수입니다. 포함 된 자세한 mean
계산 length(x)
은 x
양수가 아닌 값을 포함 하는 경우에 필요 합니다.
gm_mean = function(x, na.rm=TRUE){
exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
}
na.rm
통과 에 주목 해 주신 @ ben-bolker 와 올바르게 작동하는지 확인한 @Gregor에게 감사드립니다 .
의견 중 일부 NA
는 데이터 및 0 값 의 잘못된 동등성과 관련이 있다고 생각 합니다. 응용 프로그램에서 나는 그것들이 동일하다는 것을 염두에 두었지만 물론 이것은 일반적으로 사실이 아닙니다. 따라서 0의 선택적 전파를 포함하고 제거 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
하고 기하 평균이 음수 값에 대해 정의되지 않았다는 점을 고려 하여 더 유익하고 적절한 결과를 반환 합니다 (하지만 0에 대한 것임). 이것에 대해 내 사건에 남아있는 논평자들에게 감사드립니다.
na.rm
인수 로 전달하는 것이 더 낫지 않습니까 (즉, 사용자가 다른 R 요약 함수와의 일관성을 위해 NA 허용 여부를 결정할 수 있도록 함)? 자동으로 0을 제외하는 것에 대해 불안합니다. 옵션으로도 만들 것입니다.
na.rm
옵션으로 통과 하는 것이 맞을 것 입니다. 내 대답을 업데이트하겠습니다. 0 제외와 관련하여 기하 평균은 0을 포함하여 양수가 아닌 값에 대해 정의되지 않습니다. 위의 내용은 기하 평균에 대한 일반적인 수정 사항으로, 0 (또는이 경우 모든 0이 아닌 값)에 더미 값 1이 지정되어 제품에 영향을주지 않습니다 (또는 로그 합계에서 0).
na.rm
코드로 통과가 작동하지 않습니다 ... 참조 gm_mean(c(1:3, NA), na.rm = T)
. 당신은 제거 할 필요 & !is.na(x)
벡터 집합에서, 그리고 최초의 인수 이후 sum
이다 ...
, 당신은 통과해야 na.rm = na.rm
이름으로, 당신은 또한 제외해야 0
's와 NA
의 벡터에서의 length
호출.
x
유일한 제로 (들)을 포함, 같은 x <- 0
, exp(sum(log(x[x>0]), na.rm = TRUE)/length(x))
제공 1
이해가되지 않습니다 기하 평균을 위해.
우리는 psych 패키지 를 사용 하고 geometric.mean 함수를 호출 할 수 있습니다 .
psych::geometric.mean()
그만큼
exp(mean(log(x)))
x에 0이 없으면 작동합니다. 그렇다면 로그는 항상 기하 평균이 0 인 -Inf (-Infinite)를 생성합니다.
한 가지 해결책은 평균을 계산하기 전에 -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))])))
sum(x) / length(x)
x를 필터링 한 다음에 전달하면 평균의 분모 가 잘못 되었기 때문에 두 방법 모두 평균 이 잘못되었습니다 mean
.
이 버전은 다른 답변보다 더 많은 옵션을 제공합니다.
이를 통해 사용자는 (실제) 숫자가 아닌 결과와 사용할 수없는 결과를 구분할 수 있습니다. 음수가 있으면 답은 실수 NaN
가 아니므 로 반환됩니다. 모든 NA
값이 있으면 함수는 NA_real_
대신 실제 값을 사용할 수 없음을 반영하여 반환 합니다. 이것은 미묘한 차이이지만 (약간) 더 강력한 결과를 얻을 수 있습니다.
첫 번째 선택적 매개 변수 zero.rm
는 사용자가 0을 0으로 만들지 않고 출력에 영향을주는 0을 갖도록하기위한 것입니다. 경우 zero.rm
로 설정 FALSE
하고 eta
로 설정 NA_real_
(기본값), 제로 한 방향으로 결과를 축소의 효과가 있습니다. 나는 이것에 대한 이론적 정당성을 가지고 있지 않다. 단지 0을 무시하지 않고 자동으로 결과를 0으로 만드는 것을 포함하지 않는 "무언가"하는 것이 더 합리적이다.
eta
https://support.bioconductor.org/p/64014/ 토론에서 영감을 얻은 0을 처리하는 방법입니다.
geomean <- function(x,
zero.rm = TRUE,
na.rm = TRUE,
nan.rm = TRUE,
eta = NA_real_) {
nan.count <- sum(is.nan(x))
na.count <- sum(is.na(x))
value.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
#Handle cases when there are negative values, all values are missing, or
#missing values are not tolerated.
if ((nan.count > 0 & !nan.rm) | any(x < 0, na.rm = TRUE)) {
return(NaN)
}
if ((na.count > 0 & !na.rm) | value.count == 0) {
return(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.
if (all(x > 0, na.rm = TRUE)) {
return(exp(mean(log(x), na.rm = TRUE)))
}
if (all(x == 0, na.rm = TRUE)) {
return(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.
if (is.na(eta)) {
return(exp(sum(log(x[x > 0]), na.rm = TRUE) / value.count))
}
if (eta > 0) {
return(exp(mean(log(x + eta), na.rm = TRUE)) - eta)
}
return(0) #only propagate zeroes when eta is set to 0 (or less than 0)
}
dplyr
필요한 경우가 아니면 그러한 유틸리티와 같은 무거운 종속성을 추가하고 싶지 않습니다 ...)
case_when
s가 약간 어리 석었으므로 if
s 에 찬성하여 종속성과 종속성을 제거했습니다 . 나는 또한 약간의 정교함을 제공했다.
nan.rm
로 변경했습니다 TRUE
.
ifelse
벡터화를 위해 설계되었습니다. 확인해야 할 단일 조건으로 사용하는 것이 더 관용적입니다value.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
ifelse
. 변경되었습니다. 감사!
EnvStats 패키지 하는 기능이있다 GEOMEAN 및 geoSd을 .
exp(mean(log(x1))) == prod(x1)^(1/length(x1))