Próbowałem znaleźć wbudowaną średnią geometryczną, ale nie mogłem.
(Oczywiście wbudowany nie zaoszczędzi mi czasu podczas pracy w powłoce, ani nie podejrzewam żadnej różnicy w dokładności; w przypadku skryptów staram się używać wbudowanych tak często, jak to możliwe, gdzie (skumulowany) wzrost wydajności jest często zauważalny.
Na wypadek, gdyby nie było żadnego (co wątpię), oto moje.
gm_mean = function(a){prod(a)^(1/length(a))}
Odpowiedzi:
Oto wektoryzowana funkcja z tolerancją na zero i NA, służąca do obliczania średniej geometrycznej w R. Pełne
mean
obliczenia z udziałemlength(x)
są konieczne w przypadkach, w którychx
zawiera wartości niedodatnie.Podziękowania dla @ ben-bolker za odnotowanie
na.rm
przejścia i @Gregor za upewnienie się, że działa poprawnie.Myślę, że niektóre komentarze dotyczą fałszywej równoważności
NA
wartości w danych i zer. W aplikacji, o której myślałem, są takie same, ale oczywiście nie jest to generalnie prawda. Tak więc, jeśli chcesz uwzględnić opcjonalną propagację zer i traktowaćlength(x)
inaczej w przypadkuNA
usuwania, poniższa alternatywa jest nieco dłuższą alternatywą dla powyższej funkcji.Należy zauważyć, że sprawdza również wszelkie wartości ujemne i zwraca bardziej pouczające i odpowiednie informacje, biorąc pod uwagę,
NaN
że średnia geometryczna nie jest zdefiniowana dla wartości ujemnych (ale jest dla zer). Dziękuję komentatorom, którzy pozostali przy mojej sprawie w tej sprawie.źródło
na.rm
jako argument (tj. pozwolić użytkownikowi zdecydować, czy chce być tolerancyjny na NA, czy nie, w celu zachowania spójności z innymi funkcjami podsumowującymi R)? Boję się automatycznego wykluczania zer - również bym to zrobił.na.rm
opcji. Zaktualizuję odpowiedź. Jeśli chodzi o wykluczanie zer, średnia geometryczna jest nieokreślona dla wartości niedodatnich, w tym zer. Powyższe jest częstą poprawką dla średniej geometrycznej, w której zerom (lub w tym przypadku wszystkim różnym od zera) przypisywana jest wartość fikcyjna 1, co nie ma wpływu na iloczyn (lub równoważnie zero w sumie logarytmicznej).na.rm
przejście nie działa zgodnie z kodem ... zobaczgm_mean(c(1:3, NA), na.rm = T)
. Musisz usunąć& !is.na(x)
z podzbioru wektorów, a ponieważ pierwszy argumentsum
to...
, musisz przekazaćna.rm = na.rm
nazwę, a także musisz wykluczyć0
„iNA
” z wektora wlength
wywołaniu.x
zawiera tylko zero (s), na przykładx <- 0
,exp(sum(log(x[x>0]), na.rm = TRUE)/length(x))
podaje1
średnią geometryczną, która nie ma sensu.Nie, ale jest kilka osób, które takie napisały, na przykład tutaj .
Inną możliwością jest użycie tego:
źródło
Możemy użyć pakietu psych i wywołać funkcję geometryczną .
źródło
psych::geometric.mean()
Plik
będzie działać, chyba że jest 0 w x. Jeśli tak, dziennik wygeneruje -Inf (-Infinite), co zawsze daje średnią geometryczną równą 0.
Jednym z rozwiązań jest usunięcie wartości -Inf przed obliczeniem średniej:
Można do tego użyć linijki jednowierszowej, ale oznacza to dwukrotne obliczenie dziennika, co jest nieefektywne.
źródło
sum(x) / length(x)
jest błędny, jeśli przefiltrujesz x, a następnie przekażesz go domean
.Używam dokładnie tego, co mówi Mark. W ten sposób, nawet z tapply, możesz korzystać z wbudowanej
mean
funkcji, bez konieczności definiowania swojej! Na przykład, aby obliczyć średnie geometryczne wartości $ danych dla poszczególnych grup:źródło
Ta wersja zawiera więcej opcji niż inne odpowiedzi.
Pozwala użytkownikowi rozróżnić wyniki, które nie są (rzeczywistymi) liczbami, i te, które nie są dostępne. Jeśli obecne są liczby ujemne, odpowiedź nie będzie liczbą rzeczywistą, więc
NaN
jest zwracana. Jeśli są to wszystkieNA
wartości, funkcja zwróciNA_real_
zamiast tego odzwierciedlenie, że rzeczywista wartość jest dosłownie niedostępna. Jest to subtelna różnica, ale taka, która może dać (nieco) solidniejsze wyniki.Pierwszy opcjonalny parametr
zero.rm
ma na celu zezwolenie użytkownikowi na to, aby zera wpływały na dane wyjściowe bez zerowania go. Jeślizero.rm
jest ustawiona naFALSE
ieta
jest ustawiona naNA_real_
(wartość domyślna), zera zmniejszają wynik do jedynki. Nie mam na to żadnego teoretycznego uzasadnienia - po prostu wydaje się, że bardziej sensowne jest nie ignorowanie zer, ale „zrobienie czegoś”, co nie obejmuje automatycznego zerowania wyniku.eta
to sposób postępowania z zerami zainspirowany następującą dyskusją: https://support.bioconductor.org/p/64014/źródło
dplyr
przypadku takiego narzędzia, chyba że to konieczne ...)case_when
były trochę głupie, więc usunąłem je i zależność na korzyśćif
s. Dostarczyłem też pewnych wyjaśnień.nan.rm
na,TRUE
aby wyrównać wszystkie trzy parametry `` .rm ''.ifelse
jest przeznaczony do wektoryzacji. Z jednym warunkiem do sprawdzenia, byłoby bardziej idiomatyczne w użyciuvalue.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
ifelse
też. Zmieniony. Dzięki!Pakiet EnvStats posiada funkcję GEOMEAN i geoSd .
źródło
Jeśli w danych brakuje wartości, nie jest to rzadki przypadek. musisz dodać jeszcze jeden argument.
Możesz spróbować następującego kodu:
źródło
źródło