web-dev-qa-db-ja.com

幾何平均:組み込み機能はありますか?

幾何平均の組み込みを見つけようとしましたが、見つかりませんでした。

(明らかに、ビルトインはシェルでの作業中に時間を節約するものではありません。また、精度に違いがあるとは思わないでしょう。スクリプトでは、可能な限り頻繁にビルトインを使用しようとします多くの場合、パフォーマンスの向上が顕著です。

ここに1つも存在しない場合(疑わしい)、ここにあります。

gm_mean = function(a){prod(a)^(1/length(a))}
91
doug

Rの幾何平均を計算するためのベクトル化されたゼロおよびNA許容関数を次に示します。length(x)を含む冗長mean計算は、xにnon -正の値。

_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値の誤った同等性に関連していると思います。私が念頭に置いたアプリケーションでは、それらは同じですが、もちろんこれは一般的に真実ではありません。したがって、オプションのゼロの伝播を含め、NAを削除する場合にlength(x)を異なる方法で処理する場合、上記の関数の代わりに少し長い方法を使用できます。

_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を返します。これについて私のケースにとどまったコメンターに感謝します。

63
Paul McMurdie

いいえ、しかし here のように、これを書いた人がいます。

別の可能性はこれを使用することです:

exp(mean(log(x)))
78
Mark Byers

exp(mean(log(x)))

xに0がない限り機能します。その場合、ログは-Inf(-Infinite)を生成し、常に幾何平均が0になります。

1つの解決策は、平均を計算する前に-Inf値を削除することです。

geo_mean <- function(data) {
    log_data <- log(data)
    gm <- exp(mean(log_data[is.finite(log_data)]))
    return(gm)
}

ワンライナーを使用してこれを行うことができますが、それはログを2回計算することを意味し、非効率的です。

exp(mean(log(i[is.finite(log(i))])))
12

psychパッケージを使用して、その中でgeometric.mean関数を呼び出すことができます。

11
AliCivil

マークの言うとおりに使用します。このように、tapplyを使用しても、組み込みのmean関数を使用できます。定義する必要はありません!たとえば、data $ valueのグループごとの幾何平均を計算するには:

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

データに欠損値がある場合、これはまれなケースではありません。もう1つ引数を追加する必要があります。次のコードを試すことができます。

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

EnvStatsパッケージには、geoMeanおよびgeoSdの機能があります

2
PrinzvonK

これが私のバージョンです。 Paul McMurdieによって現在受け入れられている答えとは一線を画す以下の機能があります。

  1. na.rm == TRUEの場合、NA値は分母で無視されます。したがって、非欠損値の使用は、length(x)の代わりに分母で変数values.countをカウントします。
  2. オプションで、NaNと一般的なNAの値を区別し、それぞれに.rmパラメーターを付けます。デフォルトでは、NaNsは「悪い」ため、負の数が悪いように、NaNが返されます。欠損値を処理するための2つのパラメーターがあることは明らかに理想的ではありませんが、これらのパラメーターのデフォルトを設定し、case_whenステートメントにケースを配置する方法は、予期しない動作の可能性を回避する必要があります。
  3. 私のバージョンには、ゼロを処理する別のオプションパラメータetaが含まれています。 etaのデフォルトはNA_real_です。この場合、分母ではゼロがカウントされますが、伝播されません(受け入れられた回答のzero.propagate = FALSEオプションパラメータに類似)。正の数が渡されると、etaxに追加される人工定数として機能します(ただし、xにゼロが含まれる場合のみ)。他の数値(おそらく0)が渡されると、受け入れられた回答でzero.propagateTRUEと等しく設定された場合と同様に、ゼロが伝搬されます。

ゼロが存在するかどうかに関係なく、微調整が必​​要になる可能性があります(たとえば、etaetaが正の数である場合)を追加することをお勧めします)。関数が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)
  )
}
1
Chris Coffee