Tentei encontrar um meio geométrico integrado, mas não consegui.
(Obviamente, um built-in não vai me poupar tempo enquanto trabalho no shell, nem suspeito que haja qualquer diferença na precisão; para scripts, tento usar built-ins tão frequentemente quanto possível, onde o (cumulativo) o ganho de desempenho geralmente é perceptível.
Caso não haja (o que duvido seja o caso) aqui está o meu.
gm_mean = function(a){prod(a)^(1/length(a))}
Respostas:
Aqui está uma função vetorial, tolerante a zero e NA, para calcular a média geométrica em R. O
mean
cálculo detalhadolength(x)
é necessário para os casos em quex
contém valores não positivos.Obrigado a @ben-bolker por observar a
na.rm
passagem e a @Gregor por ter certeza de que funciona corretamente.Acho que alguns dos comentários estão relacionados a uma falsa equivalência de
NA
valores nos dados e zeros. No aplicativo que eu tinha em mente, eles são iguais, mas é claro que isso geralmente não é verdade. Portanto, se você deseja incluir a propagação opcional de zeros e tratar de formalength(x)
diferente no caso deNA
remoção, a seguinte alternativa é um pouco mais longa para a função acima.Observe que ele também verifica se há valores negativos e retorna uma informação mais informativa e apropriada,
NaN
respeitando que a média geométrica não é definida para valores negativos (mas é para zeros). Agradeço aos comentaristas que permaneceram no meu caso sobre isso.fonte
na.rm
como um argumento (ou seja, deixar o usuário decidir se deseja ser tolerante a NA ou não, para consistência com outras funções de resumo de R)? Estou nervoso sobre a exclusão automática de zeros - também faria disso uma opção.na.rm
como uma opção. Vou atualizar minha resposta. Quanto à exclusão de zeros, a média geométrica é indefinida para valores não positivos, incluindo zeros. O acima é uma correção comum para a média geométrica, em que zeros (ou, neste caso, todos os diferentes de zero) recebem um valor fictício de 1, que não tem efeito sobre o produto (ou, equivalentemente, zero na soma logarítmica).na.rm
passagem não funciona como codificada ... vejagm_mean(c(1:3, NA), na.rm = T)
. Você precisa remover o& !is.na(x)
do subconjunto do vetor e, como o primeiro argumento desum
é...
, você precisa passarna.rm = na.rm
por nome e também precisa excluir0
's eNA
' s do vetor nalength
chamada.x
conter apenas zero (s), assimx <- 0
,exp(sum(log(x[x>0]), na.rm = TRUE)/length(x))
dá1
para a média geométrica, o que não faz sentido.Não, mas há algumas pessoas que escreveram um, como aqui .
Outra possibilidade é usar:
fonte
Podemos usar o pacote psych e chamar a função geometric.mean .
fonte
psych::geometric.mean()
o
funcionará a menos que haja um 0 em x. Nesse caso, o log produzirá -Inf (-Infinite) que sempre resulta em uma média geométrica de 0.
Uma solução é remover o valor -Inf antes de calcular a média:
Você pode usar uma linha única para fazer isso, mas significa calcular o log duas vezes, o que é ineficiente.
fonte
sum(x) / length(x)
está errado se você filtrar x e depois passá-lo paramean
.Eu uso exatamente o que Mark diz. Desta forma, mesmo com tapply, você pode usar a
mean
função embutida, sem precisar definir a sua! Por exemplo, para calcular médias geométricas por grupo de dados $ value:fonte
Esta versão oferece mais opções do que as outras respostas.
Permite ao usuário distinguir entre resultados que não são números (reais) e aqueles que não estão disponíveis. Se números negativos estiverem presentes, a resposta não será um número real, então
NaN
é retornado. Se todos foremNA
valores, a função retornará emNA_real_
vez disso para refletir que um valor real literalmente não está disponível. Esta é uma diferença sutil, mas que pode produzir resultados (ligeiramente) mais robustos.O primeiro parâmetro opcional
zero.rm
destina-se a permitir que o usuário faça com que os zeros afetem a saída sem torná-la zero. Sezero.rm
estiver definido comoFALSE
eeta
estiver definido comoNA_real_
(seu valor padrão), os zeros têm o efeito de reduzir o resultado para um. Não tenho nenhuma justificativa teórica para isso - apenas parece fazer mais sentido não ignorar os zeros, mas "fazer algo" que não envolva tornar o resultado zero automaticamente.eta
é uma maneira de lidar com zeros que foi inspirada na seguinte discussão: https://support.bioconductor.org/p/64014/fonte
dplyr
para tal utilitário, a menos que necessário ...)case_when
s eram um pouco bobos, então eu os retirei e a dependência em favor deif
s. Eu também forneci alguns detalhes.nan.rm
paraTRUE
para alinhar todos os três parâmetros `` `.rm``.ifelse
é projetado para vetorização. Com uma única condição para verificar, seria mais idiomático de usarvalue.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
ifelse
também. Alterado. Obrigado!O pacote EnvStats tem uma função para geoMean e geoSd .
fonte
Caso haja valores ausentes em seus dados, esse não é um caso raro. você precisa adicionar mais um argumento.
Você pode tentar o seguinte código:
fonte
fonte