J'ai essayé de trouver une moyenne géométrique intégrée mais je n'ai pas pu.
(De toute évidence, un intégré ne me fera pas gagner de temps lorsque je travaille dans le shell, et je ne soupçonne pas non plus qu'il y ait une différence de précision; pour les scripts, j'essaie d'utiliser des intégrés aussi souvent que possible, où le (cumulatif) le gain de performances est souvent perceptible.
Au cas où il n'y en aurait pas (ce dont je doute que ce soit le cas), voici le mien.
gm_mean = function(a){prod(a)^(1/length(a))}
Réponses:
Voici une fonction vectorisée, tolérante à zéro et NA pour le calcul de la moyenne géométrique en R. Le
mean
calcul détaillé impliquantlength(x)
est nécessaire pour les cas oùx
contient des valeurs non positives.Merci à @ ben-bolker pour avoir noté le
na.rm
passage et @Gregor pour s'assurer qu'il fonctionne correctement.Je pense que certains des commentaires sont liés à une fausse équivalence des
NA
valeurs dans les données et des zéros. Dans l'application que j'avais en tête, ce sont les mêmes, mais bien sûr ce n'est généralement pas vrai. Ainsi, si vous souhaitez inclure la propagation facultative des zéros, et traiterlength(x)
différemment en cas deNA
suppression, voici une alternative légèrement plus longue à la fonction ci-dessus.Notez qu'il vérifie également les valeurs négatives et renvoie une valeur plus informative et plus appropriée en
NaN
ce qui concerne le fait que la moyenne géométrique n'est pas définie pour les valeurs négatives (mais pour les zéros). Merci aux commentateurs qui sont restés sur mon cas à ce sujet.la source
na.rm
en argument (c'est-à-dire de laisser l'utilisateur décider s'il veut être tolérant à NA ou non, par souci de cohérence avec les autres fonctions de résumé R)? Je suis nerveux à l'idée d'exclure automatiquement les zéros - j'en ferais également une option.na.rm
comme une option. Je mettrai à jour ma réponse. Quant à l'exclusion des zéros, la moyenne géométrique n'est pas définie pour les valeurs non positives, y compris les zéros. Ce qui précède est une solution courante pour la moyenne géométrique, dans laquelle les zéros (ou dans ce cas tous les non-zéros) reçoivent une valeur fictive de 1, ce qui n'a aucun effet sur le produit (ou, de manière équivalente, zéro dans la somme logarithmique).na.rm
pass-through ne fonctionne pas comme codé ... voyezgm_mean(c(1:3, NA), na.rm = T)
. Vous devez supprimer le& !is.na(x)
du sous-ensemble vectoriel, et comme le premier argument desum
est...
, vous devez passerna.rm = na.rm
par nom, et vous devez également exclure0
les etNA
du vecteur dans l'length
appel.x
ne contenir que zéro (s), commex <- 0
,exp(sum(log(x[x>0]), na.rm = TRUE)/length(x))
donne1
la moyenne géométrique, ce qui n'a pas de sens.Non, mais il y a quelques personnes qui en ont écrit un, comme ici .
Une autre possibilité est d'utiliser ceci:
la source
Nous pouvons utiliser le package psych et appeler la fonction géométrique.mean .
la source
psych::geometric.mean()
le
fonctionnera sauf s'il y a un 0 dans x. Si tel est le cas, le journal produira -Inf (-Infinite) qui aboutit toujours à une moyenne géométrique de 0.
Une solution consiste à supprimer la valeur -Inf avant de calculer la moyenne:
Vous pouvez utiliser une ligne pour ce faire, mais cela signifie calculer le journal deux fois, ce qui est inefficace.
la source
sum(x) / length(x)
est faux si vous filtrez x puis le passez àmean
.J'utilise exactement ce que dit Mark. De cette façon, même avec tapply, vous pouvez utiliser la
mean
fonction intégrée, pas besoin de définir la vôtre! Par exemple, pour calculer les moyennes géométriques par groupe de données $ value:la source
Cette version offre plus d'options que les autres réponses.
Il permet à l'utilisateur de faire la distinction entre les résultats qui ne sont pas des nombres (réels) et ceux qui ne sont pas disponibles. Si des nombres négatifs sont présents, la réponse ne sera pas un nombre réel, elle
NaN
est donc renvoyée. S'il s'agit de toutes lesNA
valeurs, la fonction retournera à laNA_real_
place pour indiquer qu'une valeur réelle n'est littéralement pas disponible. Il s'agit d'une différence subtile, mais qui pourrait donner des résultats (légèrement) plus robustes.Le premier paramètre facultatif
zero.rm
est destiné à permettre à l'utilisateur d'avoir des zéros affectant la sortie sans la rendre nulle. Sizero.rm
est défini surFALSE
eteta
est défini surNA_real_
(sa valeur par défaut), les zéros ont pour effet de réduire le résultat vers un. Je n'ai aucune justification théorique pour cela - il semble juste plus logique de ne pas ignorer les zéros mais de "faire quelque chose" qui n'implique pas de rendre automatiquement le résultat nul.eta
est une façon de gérer les zéros qui a été inspirée par la discussion suivante: https://support.bioconductor.org/p/64014/la source
dplyr
case_when
s étaient un peu ridicules, alors je les ai supprimés et la dépendance en faveur de l'if
art. J'ai également fourni quelques précisions.nan.rm
pourTRUE
aligner les trois `` `paramètres .rm``.ifelse
est conçu pour la vectorisation. Avec une seule condition à vérifier, il serait plus idiomatique à utiliservalue.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
ifelse
aussi. Modifié. Merci!Le package EnvStats a une fonction pour geoMean et geoSd .
la source
Au cas où il y aurait des valeurs manquantes dans vos données, ce n'est pas un cas rare. vous devez ajouter un argument supplémentaire.
Vous pouvez essayer le code suivant:
la source
la source