几何意义:是否有内置?

时间:2010-04-08 18:49:54

标签: r statistics built-in geometric-mean

我试图找到几何平均值的内置但不能。

(显然内置在shell中工作时不会省时间,我也不怀疑准确性有任何差别;对于脚本,我尝试尽可能多地使用内置函数,其中(累积)性能提升通常是显而易见的。

如果没有(我怀疑是这种情况),这里是我的。

gm_mean = function(a){prod(a)^(1/length(a))}

9 个答案:

答案 0 :(得分:77)

不,但是有一些人写了一个,例如here

另一种可能性是使用它:

exp(mean(log(x)))

答案 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当前接受的答案区分开来:

  1. na.rm == TRUE时,分母中的NA值将被忽略-因此,使用非缺失值计算分母中的变量values.count而不是length(x)
  2. 它可以选择区分NaN和通用NA值,并分别为.rm参数。默认情况下,NaN是“坏的”,就像负数是坏的一样,因此返回NaN。具有两个用于处理缺失值的参数显然不是理想的选择,但是我为这些参数设置默认值并在case_when语句中排列案例的方式应该(希望)消除意外行为的可能性。
  3. 我的版本包括另一个用于处理零的可选参数etaeta默认为NA_real_,在这种情况下,零在分母中计数但不传播(类似于接受的答案中的zero.propagate = FALSE可选参数)。当传递正数时,eta充当要添加到x的人工常数(但仅在x包含零的情况下)。当传递任何其他数字(大概为0)时,零将传播,就像在接受的答案中将zero.propagate设置为等于TRUE一样。

我确定可能需要进行调整(例如,最好添加eta(假设eta是一个正数),无论是否存在零) 。我甚至考虑过让该函数根据etax动态选择一个值,但选择不增加任何复杂性。

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))