我试图找到几何平均值的内置但不能。
(显然内置在shell中工作时不会省时间,我也不怀疑准确性有任何差别;对于脚本,我尝试尽可能多地使用内置函数,其中(累积)性能提升通常是显而易见的。
如果没有(我怀疑是这种情况),这里是我的。
gm_mean = function(a){prod(a)^(1/length(a))}
答案 0 :(得分:77)
答案 1 :(得分:59)
这是一个用于计算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))
}
计算积极的价值观。
na.rm
感谢@ ben-bolker注意到NA
传递和@Gregor以确保其正常工作。
我认为有些评论与数据和零中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
请注意,它还会检查任何负值,并返回更具信息性和适当性{{1}},因为没有为负值定义几何平均值(但是为零)。感谢评论此事的评论者。
答案 2 :(得分:12)
exp(mean(log(x)))
除非x中有0,否则将起作用。如果是这样,日志将产生-Inf(-Infinite),它总是导致几何平均值为0.
一种解决方案是在计算平均值之前删除-Inf值:
geo_mean <- function(data) {
log_data <- log(data)
gm <- exp(mean(log_data[is.finite(log_data)]))
return(gm)
}
您可以使用单行来执行此操作,但这意味着计算两次效率很低的日志。
exp(mean(log(i[is.finite(log(i))])))
答案 3 :(得分:11)
您可以使用psych
包并在其中调用geometric.mean
函数。
答案 4 :(得分:6)
我正好用Mark所说的。这样,即使使用tapply,您也可以使用内置的mean
函数,无需定义您的!例如,要计算每组数据的几何平均值$ value:
exp(tapply(log(data$value), data$group, mean))
答案 5 :(得分:3)
如果您的数据中缺少值,这种情况并不罕见。 你需要再添加一个参数。 您可以尝试使用以下代码。
exp(mean(log(i[is.finite(log(i))]),na.rm=T))
答案 6 :(得分:2)
EnvStats包具有geoMean和geoSd
的功能答案 7 :(得分:1)
这是我的版本。它具有以下功能使其与Paul McMurdie当前接受的答案区分开来:
na.rm == TRUE
时,分母中的NA
值将被忽略-因此,使用非缺失值计算分母中的变量values.count
而不是length(x)
。NaN
和通用NA
值,并分别为.rm
参数。默认情况下,NaN
是“坏的”,就像负数是坏的一样,因此返回NaN
。具有两个用于处理缺失值的参数显然不是理想的选择,但是我为这些参数设置默认值并在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)
)
}
答案 8 :(得分:1)
exp(mean(log(x1))) == prod(x1)^(1/length(x1))