【问题标题】:which.min on a subset of a vectorwhich.min 在向量的子集上
【发布时间】:2015-07-07 02:15:14
【问题描述】:

我想获取某个向量子集的最小值的索引,但要获取原始向量中的索引,而不是重新编号的子集。

就目前而言,我一直在使用:

L = rnorm(20) # say this is the original vector
subset = runif(20)<0.3 # some conditions to extract the subset
ind_min = which.min(L[subset])
ind_sel = seq(L)[subset]
ind_min = ind_sel[ind_min]

但我想应该有更直接或更干净的东西。我一直在考虑使用一种技巧,例如:

L_tmp = L
L_tmp[!subset] = Inf
ind_min = which.min(L_tmp)

这显然更有效:

> microbenchmark(method_1(), method_2(), unit = "relative")
Unit: relative
       expr      min       lq     mean   median       uq      max neval
 method_1() 3.699562 3.249635 3.119666 3.076819 2.928259 3.225849   100
 method_2() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100

但我对它并不满意,因为我想应该还有别的东西。有什么建议吗?

【问题讨论】:

    标签: r sorting vector


    【解决方案1】:

    你可以试试:

    (seq(L))[subset][which.min(L[subset])]
    

    这类似于您的第一种方法,但不创建临时变量

    在 20000 长向量 L 上进行基准测试:

        method_cath<- function(){(seq(L))[subset][which.min(L[subset])]}
        method_FK_corr1 <- function(){min = min(L[subset])
                                      ind_min = intersect(which(L == min), seq(L)[subset])[1]
                                      return(ind_min)} 
        method_FK_corr2 <- function(){min = min(L[subset])
                                      ind_min = intersect(which(L == min), which(subset))[1]
                                      return(ind_min)} 
        method_1clm <- function(){ind_min = which.min(L[subset])
                                  ind_sel = seq(L)[subset]
                                  ind_min = ind_sel[ind_min]
                                  return(ind_min)} 
        method_2clm <- function(){L_tmp = L
                                  L_tmp[!subset] = Inf
                                  ind_min = which.min(L_tmp)
                                  return(ind_min)}
    
    > microbenchmark(method_2clm(), method_cath(), method_1clm(), method_FK_corr2(), method_FK_corr1(), unit = "relative")
       # Unit: relative
       #               expr      min       lq     mean   median       uq       max neval cld
       #      method_2clm() 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000   100 a  
       #      method_cath() 1.312146 1.290370 1.282964 1.278178 1.282424 0.9191693   100  b 
       #      method_1clm() 1.295031 1.294642 1.303781 1.284630 1.279821 1.2977193   100  b 
       #  method_FK_corr2() 1.185821 1.166924 1.278030 1.155217 1.165738 4.9948007   100  b 
       #  method_FK_corr1() 1.683783 1.644797 1.746055 1.635293 1.636195 5.1616672   100   c
    

    注意:我使用 @FedorenkoKristina 原始函数得到了 NA,我测试了 2 个可能的更正函数,现在所有函数都给出相同的结果。

    【讨论】:

      【解决方案2】:

      您可以在L[subset] 中找到 min。然后获取L中的索引。

      L = rnorm(20) # say this is the original vector
      subset = runif(20)<0.3 # some conditions to extract the subset
      min = min(L[subset])
      ind_min = intersect(which(L == min), seq(L)[subset])[1]
      

      【讨论】:

      • 请记住,which.min 会找到第一个最小值,而 which 会找到满足条件的所有值。
      • 显然和我的第二个选项一样快,但都适合一行:ind_min = intersect(which(L == min(L[subset])), seq(L)[subset]) 所以它可能会更好!顺便说一句有错误,你应该添加seq(L)[subset]
      • @clemlaflemme this: (seq(L))[subset][which.min(L[subset])] 与您尝试过的类似,也适合一行;-)
      • 不知道我可以一个接一个地放几个括号!但建议的选项更快
      • @clemlaflemme,我不太确定,请查看我的答案和 20000 长向量的基准测试结果
      【解决方案3】:

      也许您也可以使用子集。子集是您的条件。

      L = rnorm(20) # say this is the original vector
      subset = runif(20)<0.3 # some conditions to extract the subset
      ind_min = which(L == min(subset(L,subset)))
      

      我想这与 Fedorenko Kristina 的建议非常相似。她比我快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多