developer tip

기하 평균 : 내장 기능이 있습니까?

optionbox 2020. 9. 1. 07:26
반응형

기하 평균 : 내장 기능이 있습니까?


기하 평균에 대한 내장을 찾으려고했지만 찾을 수 없었습니다.

(분명히 빌트인은 쉘에서 작업하는 동안 저를 절약 해주지 않을 것이며 정확도에 차이가 있다고 생각하지도 않습니다. 스크립트의 경우 빌트인을 가능한 한 자주 사용하려고합니다. 성능 향상은 종종 눈에 띄게 나타납니다.

(내가 의심하는) 하나가 없다면 여기 내 것입니다.

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에 대한 것임). 이것에 대해 내 사건에 남아있는 논평자들에게 감사드립니다.


아니요,하지만 여기 와 같이 글을 쓴 사람이 몇 명 있습니다 .

또 다른 가능성은 이것을 사용하는 것입니다.

exp(mean(log(x)))

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))])))

마크가 말한 그대로 사용합니다. 이렇게하면 tapply를 사용해도 내장 mean기능을 사용할 수 있으며, 자신의 기능을 정의 할 필요가 없습니다! 예를 들어, data $ value의 그룹 별 기하학적 평균을 계산하려면 다음을 수행하십시오.

exp(tapply(log(data$value), data$group, mean))

데이터에 결 측값이있는 경우 드문 경우가 아닙니다. 인수를 하나 더 추가해야합니다. 다음 코드를 시도해 볼 수 있습니다.

exp(mean(log(i[is.finite(log(i))]),na.rm=T))

EnvStats 패키지에는 geoMean 및 geoSd에 대한 기능이 있습니다.


Here is my version. It has the following features that set it apart from the currently accepted answer by Paul McMurdie:

  1. When na.rm == TRUE, NA values are ignored in the denominator - hence the use of non-missing values count variable values.count in the denominator instead of length(x).
  2. It optionally distinguishes between NaN and generic NA values, with a .rm parameter for each. By default, NaNs are "bad", just like negative numbers are bad, so NaN is returned. Having two parameters for handling missing values is obviously not ideal, but the way I set the defaults for these parameters and arranged the cases in the case_when statement should (hopefully) obviate the possibility of unexpected behavior.
  3. My version includes another optional parameter eta that handles zeroes. eta defaults to NA_real_, in which case zeros are counted in the denominator but not propagated (analogous to the zero.propagate = FALSE optional parameter in the accepted answer). When a positive number is passed, eta functions as an artificial constant to be added to x (but only in the event that x contains zeroes). When any other number is passed (presumably 0), zeroes are propagated, just as when zero.propagate is set equal to TRUE in the accepted answer.

I'm sure tweaks may be called for (for instance, it may be best to add eta (given that eta is a positive number) regardless of whether there are or are not zeroes). I thought about even having the function dynamically choose a value for eta based on x but opted against adding any further complexity.

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)
  )
}

참고URL : https://stackoverflow.com/questions/2602583/geometric-mean-is-there-a-built-in

반응형