【问题标题】:Return vector position in list r返回列表 r 中的向量位置
【发布时间】:2023-03-28 05:51:01
【问题描述】:

我正在尝试确定我创建的列表中元素来自的向量。我将在这里给出一个可重复的示例:

set.seed(101)
a <- runif(10, min=0, max=100)
b <- runif(10, min=0, max=100)
c <- runif(10, min=0, max=100)
d <- runif(10, min=0, max=100)

information <- list(a, b, c, d)

information.wanted <- mean(do.call(pmax, information))

获取信息的代码。想要的工作正常。我现在要查找的是列表中每个最大值来自的单个向量。例如,information.wanted (87.97...) 中的值 1 来自信息列表中的向量 b。我想创建另一段代码,给出 information.wanted 来自的向量。

> information.wanted
 [1] 87.97957 95.68375 73.19726 93.16344 92.33189 91.34787 82.04361 81.42830 62.20120
[10] 92.48044

我不知道如何做到这一点。我尝试过的任何代码都没有让我接近。

postition.of.information.wanted <- ?? 

我正在寻找这样的东西。数字向量很好。我可以稍后补充这些值。

> position.of.informaiton.wanted
[1] 2 3 ...

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 所有值都是唯一的吗?
  • 可以试试apply(do.call(rbind, information), 2, which.max)也许
  • 不一定。如果假设所有值都是唯一的,那么我可以尝试一个更简单的解决方案。该数据集是一个大型数值模拟 - 列表包含 13 个向量,每个向量有 10,000 个元素,因此在不同位置肯定有可能存在重复
  • apply(do.call(rbind, information), 2, which.max) 似乎工作得很好。谢谢!

标签: r list vector data-manipulation


【解决方案1】:

您需要将which.max应用于“信息”中每个元素的每个“i”索引:

f1 = function(x)
    sapply(seq_along(x[[1]]), function(i) which.max(sapply(x, "[[", i)))
f1(information)
# [1] 2 3 2 2 3 4 2 4 1 4

mapply 已经提供了这种“并行”功能:

f2 = function(x)
    unlist(.mapply(function(...) which.max(c(...)), x, NULL))
f2(information)
# [1] 2 3 2 2 3 4 2 4 1 4

或者,不是将“信息”连接成块,而是转换为“矩阵”——正如 David Arenburg 在 cmets 中指出的那样——在开始时将 apply which.max 转换为它的行:

f3a = function(x)
    apply(do.call(cbind, x), 1, which.max)
f3a(information)
# [1] 2 3 2 2 3 4 2 4 1 4

或其列:

f3b = function(x)
    apply(do.call(rbind, x), 2, which.max)
f3b(information)
# [1] 2 3 2 2 3 4 2 4 1 4

另外,max.col 便于“矩阵”:

f4 = function(x)
    max.col(do.call(cbind, x), "first")
f4(information)
# [1] 2 3 2 2 3 4 2 4 1 4

如果不是 R,那么元素上的简单循环将同时提供 which.maxmax ...但是 R 也处理向量:

f5 = function(x)
{
     ans = rep_len(1L, length(x[[1]]))
     maxs = x[[1]]
     for(i in 2:length(x)) {
         wh = x[[i]] > maxs
         maxs[wh] = x[[i]][wh]
         ans[wh] = i 
    }
    ans #or '(data.frame(i = ans, val = maxs)' for both
}
f5(information)
# [1] 2 3 2 2 3 4 2 4 1 4

它必须以基准结束:

set.seed(007)
dat = replicate(13, runif(1e4), FALSE)

identical(f1(dat), f2(dat))
#[1] TRUE
identical(f2(dat), f3a(dat))
#[1] TRUE
identical(f3a(dat), f3b(dat))
#[1] TRUE
identical(f3b(dat), f4(dat))
#[1] TRUE
identical(f4(dat), f5(dat))
#[1] TRUE

microbenchmark::microbenchmark(f1(dat), f2(dat), f3a(dat), f3b(dat), f4(dat), f5(dat), do.call(pmax, dat), times = 50)
#Unit: microseconds
#               expr        min         lq       mean     median         uq        max neval  cld
#            f1(dat) 274995.963 298662.210 339279.948 318937.172 350822.539 723673.972    50    d
#            f2(dat)  94619.397 100079.205 114664.776 107479.127 114619.439 226733.260    50   c 
#           f3a(dat)  19767.925  23423.688  26382.919  25795.499  29215.839  40100.656    50  b  
#           f3b(dat)  20351.872  22829.997  28889.845  25090.446  30503.100 140311.058    50  b  
#            f4(dat)    975.102   1109.431   1546.571   1169.462   1361.733   8954.100    50 a   
#            f5(dat)   2427.665   2470.816   5299.386   2520.755   3197.793 112986.612    50 a   
# do.call(pmax, dat)   1477.618   1530.166   1627.934   1551.046   1602.898   2814.295    50 a

【讨论】:

  • 感谢您的深入回答和添加基准。很有帮助!
猜你喜欢
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 2017-07-11
相关资源
最近更新 更多