幾何平均の組み込みを見つけようとしましたが、見つかりませんでした。
(明らかに、ビルトインはシェルでの作業中に時間を節約するものではありません。また、精度に違いがあるとは思わないでしょう。スクリプトでは、可能な限り頻繁にビルトインを使用しようとします多くの場合、パフォーマンスの向上が顕著です。
ここに1つも存在しない場合(疑わしい)、ここにあります。
gm_mean = function(a){prod(a)^(1/length(a))}
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
を返します。これについて私のケースにとどまったコメンターに感謝します。
の
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))])))
psych
パッケージを使用して、その中でgeometric.mean
関数を呼び出すことができます。
マークの言うとおりに使用します。このように、tapplyを使用しても、組み込みのmean
関数を使用できます。定義する必要はありません!たとえば、data $ valueのグループごとの幾何平均を計算するには:
exp(tapply(log(data$value), data$group, mean))
データに欠損値がある場合、これはまれなケースではありません。もう1つ引数を追加する必要があります。次のコードを試すことができます。
exp(mean(log(i[is.finite(log(i))]),na.rm=T))
EnvStatsパッケージには、geoMeanおよびgeoSdの機能があります
これが私のバージョンです。 Paul McMurdieによって現在受け入れられている答えとは一線を画す以下の機能があります。
na.rm == TRUE
の場合、NA
値は分母で無視されます。したがって、非欠損値の使用は、length(x)
の代わりに分母で変数values.count
をカウントします。NaN
と一般的なNA
の値を区別し、それぞれに.rm
パラメーターを付けます。デフォルトでは、NaN
sは「悪い」ため、負の数が悪いように、NaN
が返されます。欠損値を処理するための2つのパラメーターがあることは明らかに理想的ではありませんが、これらのパラメーターのデフォルトを設定し、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)
)
}