【问题标题】:Geometric mean of rows in a data table in RR中数据表中行的几何平均值
【发布时间】:2017-01-19 11:59:22
【问题描述】:

我有一个数据表,我想在其中计算几列中每一行的几何平均值。有些值会为零,所以我需要将它们排除在外。

来自 Wiki 的几何平均值是:“几何平均值被定义为 n 个数字的乘积的 n 次根”,因此对于 2 个数字,它只是它们乘积的平方根。

在我的例子中,每行的第 n 个根会有所不同,具体取决于其中有多少非零值。

在我下面的示例中,结果列的前 2 行的计算方式如下:

1: (a * c)^(1/2)

2: (a * b * c)^(1/3)

所以我需要公式来查看列 a:c,取非零值的乘积,然后取有多少非零值的 n 次根。

library(data.table)
dt <- data.table(a = c(0.5, 0.3,0,0.6), b = c(0,0.4,0.1,0), 
c = c(0.9,0.5,0.1,0), Result = c(0.67, 0.39, 0.1, 0.6))

【问题讨论】:

  • 是预期输出的“结果”吗
  • 所有数字都是非负数吗?
  • 抱歉,结果是预期的输出,所有值都是非负数。

标签: r data.table


【解决方案1】:

我们可以尝试使用data.table 方法

dt[, v1 := Reduce(`+`, lapply(.SD, function(x) x!=0)), .SDcols = 1:3]
dt[, result2 := round((Reduce(`*`, lapply(.SD, function(x) 
    replace(x, x==0, 1))))^(1/v1), 2), .SDcols = 1:3][, v1 := NULL][]
#    a   b   c Result result2
#1: 0.5 0.0 0.9   0.67    0.67
#2: 0.3 0.4 0.5   0.39    0.39
#3: 0.0 0.1 0.1   0.10    0.10
#4: 0.6 0.0 0.0   0.60    0.60

或者另一个效率较低的选项是按行序列分组,然后在每一行上进行分组

dt[, result2 := {
           u1 <- unlist(.SD)
           round(prod(u1[u1!=0])^(1/sum(u1!=0)), 2)} , 1:nrow(dt), .SDcols = 1:3]
dt
#     a   b   c Result result2
#1: 0.5 0.0 0.9   0.67    0.67
#2: 0.3 0.4 0.5   0.39    0.39
#3: 0.0 0.1 0.1   0.10    0.10
#4: 0.6 0.0 0.0   0.60    0.60

注意:这两个都是data.table 方法。

或@DavidArenburg 提供的另一个选项

dt[, Result := round(Reduce(`*`, replace(.SD, .SD == 0, 1))^(1/rowSums(.SD != 0)), 2)]

另一个矢量化选项是转换为matrix

library(matrixStats)
m1 <- as.matrix(setDF(dt)[1:3])
round(rowProds(replace(m1, !m1, 1))^(1/rowSums(m1!=0)), 2)
#[1] 0.67 0.39 0.10 0.60

【讨论】:

  • 代码块 `dt[, result2....' 返回错误... eval(expr, envir, enclos) 中的错误:找不到对象 'v1'
  • @MidnightDataGeek 你有哪个版本的data.table?我正在使用1.10.0
  • 我使用的是 1.9.6。我已经修改了下面的答案,严格来说它仍然是“data.table”方法吗?速度对我来说很关键,所以我尝试将 DT 用于一切,
  • @MidnightDataGeek 好的,这就是原因,在 1.10.0 中,使用.SDcols 时也可以访问其他列。是的,前两个是 data.table 方法。但是,如果你使用apply,它可以转换为matrix,使用data.table没有任何好处
  • 可能简单一点dt[, Result := round(Reduce(`*`, replace(.SD, .SD == 0, 1))^(1/rowSums(.SD != 0)), 2)]
【解决方案2】:

假设所有非负值,这也将起作用。

dt$Result <- apply(dt, 1, function(x) (prod(x[x!=0]))^(1/sum(x!=0)))
dt
#     a   b   c    Result
#1: 0.5 0.0 0.9 0.6708204
#2: 0.3 0.4 0.5 0.3914868
#3: 0.0 0.1 0.1 0.1000000
#4: 0.6 0.0 0.0 0.6000000

【讨论】:

  • 谢谢。我已根据需要对其进行了修改...dt[, Result := apply(.SD, 1, function(x) (prod(x[x != 0])) ^ (1/sum(x!=0))), .SDcols = 1:3]
【解决方案3】:

prod(a)^(1/length(a)) 给出向量 a 的几何平均值

【讨论】:

  • 如此处所述,上面被投票的 geomean 等式是错误的!它是 1/n 次方。不应该有“总和”。我很惊讶以前没有人支持这条评论!
【解决方案4】:

其他选项:

m1 <- as.matrix(setDF(dt)[1:3])
exp(rowMeans(log(m1)))

【讨论】:

    猜你喜欢
    • 2021-02-16
    • 2021-10-13
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多