幾何平均の組み込みを見つけようとしましたが、できませんでした。
(明らかに、シェルで作業している間、ビルトインが時間を節約することはありませんし、精度に違いがあるとは思いません。スクリプトについては、可能な限り頻繁にビルトインを使用しようとします。多くの場合、パフォーマンスの向上が顕著です。
ない場合(そうではないかと思いますが)、ここに私のものがあります。
gm_mean = function(a){prod(a)^(1/length(a))}
幾何平均の組み込みを見つけようとしましたが、できませんでした。
(明らかに、シェルで作業している間、ビルトインが時間を節約することはありませんし、精度に違いがあるとは思いません。スクリプトについては、可能な限り頻繁にビルトインを使用しようとします。多くの場合、パフォーマンスの向上が顕著です。
ない場合(そうではないかと思いますが)、ここに私のものがあります。
gm_mean = function(a){prod(a)^(1/length(a))}
以下は、R で幾何平均を計算するためのベクトル化された、ゼロおよび NA 許容関数です。非正の値が含まれる場合には、詳細な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
幾何平均が負の値に対して定義されていない (ゼロに対して定義されている) ことを考慮して、より有益で適切な値を返すことに注意してください。これについて私のケースにとどまってくれたコメンテーターに感謝します。
psych パッケージを使用して、 geometric.mean関数を呼び出すことができます。
The
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))])))
私はマークが言うことを正確に使用します。このように、tapply を使用しても、組み込みmean
関数を使用できます。独自の関数を定義する必要はありません。たとえば、data$value のグループごとの幾何平均を計算するには、次のようにします。
exp(tapply(log(data$value), data$group, mean))
このバージョンは、他の回答よりも多くのオプションを提供します。
これにより、ユーザーは (実数の) 数値ではない結果と利用できない結果を区別できます。負の数が存在する場合、答えは実数にならないため、NaN
が返されます。それがすべてのNA
値である場合、関数はNA_real_
代わりに戻り、実際の値が文字通り利用できないことを反映します。これは微妙な違いですが、(わずかに) より確実な結果が得られる可能性があります。
最初のオプションのパラメーターzero.rm
は、ユーザーが出力をゼロにせずにゼロに影響を与えることができるようにすることを目的としています。zero.rm
が に設定されFALSE
、eta
が(デフォルト値) に設定されている場合NA_real_
、ゼロは結果を 1 に向かって縮小する効果があります。これに対する理論的な正当化はありません。ゼロを無視するのではなく、結果を自動的にゼロにすることを含まない「何かをする」方が理にかなっているようです。
eta
次の議論に触発されたゼロを処理する方法です: https://support.bioconductor.org/p/64014/
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)
}