【问题标题】:Get lengths of multiple vector subsets defined by a vector of subset parameters获取由子集参数向量定义的多个向量子集的长度
【发布时间】:2014-05-22 11:54:26
【问题描述】:

我有一个由 n 元素组成的向量 x。

现在我想获得方案s = subset(x, x<=p) 的该向量的多个子集,其中p 将包含多个值,通过向量给出。

最后,我希望根据包含p 值的向量将这些子集的长度存储在一个向量中。

你能帮我在没有循环等的情况下这样做吗?

【问题讨论】:

    标签: r vector


    【解决方案1】:

    另一种占用内存较少的解决方案:

    set.seed(42)
    x <- rnorm(20) 
    p <- c(-1, 0, 1)
    ## sapply(p, function(pi) sum(x <= pi))
    [1] 1 5 8
    

    基准测试:

    library(microbenchmark)
    set.seed(42)
    x <- rnorm(20000)
    p <- rnorm(100)
    microbenchmark(setNames(colSums(outer(x, p, "<=")), p), sapply(p, function(pi) sum(x <= pi)))
    ## Unit: milliseconds
    ##                                     expr      min       lq  median       uq      max neval
    ##  setNames(colSums(outer(x, p, "<=")), p) 29.33870 87.21804 88.5226 89.94144 94.34427   100
    ##     sapply(p, function(pi) sum(x <= pi)) 21.52853 22.23344 22.2959 22.46226 26.13650   100
    

    【讨论】:

    • 但这不是“没有循环”(我认为他们只想要 C 级循环)。
    • 但是sapply 使用lapply 和lapply 调用.Internal(lapply(X, FUN)) - 这是一个“C 级循环”
    • 我不太同意。毕竟,for 也是用 C 实现的。在这两种情况下,您都将 R 表达式/函数传递给循环函数。
    • 不管怎样,玩outer 有点贵(尤其是对于大p 和x).. 我在上面添加了一些基准
    • 谢谢,这正是我所需要的! :)
    【解决方案2】:
    set.seed(42)
    x <- rnorm(20) 
    p <- c(-1, 0, 1)
    
    setNames(colSums(outer(x, p, "<=")), p)
    #-1  0  1 
    # 3 10 14 
    

    解释:

    在outer 中使用&lt;= 测试x 的每个元素与p 的每个元素。计算 colwise 和给出每个 p 值的 TRUE 值的数量。最后,我们使用p 值作为名称。

    【讨论】:

    • 感谢您的回答!由于我的数据向量不大,我并不关心速度,所以这个一样好。
    【解决方案3】:

    只是为了好玩,让我们用 Rcpp 来做。在这里,我先对输入进行排序,然后再利用它:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    NumericVector countsmaller(NumericVector x, const NumericVector p) {
      x=x.sort();
      NumericVector sorted = clone(p).sort();
      IntegerVector order=match(p, sorted);
      int count = 0;
      double prob=sorted(0);
      int i=0;
       for(int j = 0; j < x.size(); ++j) {
          if (x(j) <= prob) 
          {
            count++;
          } 
          else 
          {
            if (i < sorted.size()-1)
            {
              sorted(i)=count;
              i++;
              prob=sorted(i);  
              if (x(j) <= prob) count++; else j--;
            }
          }
        }
        sorted(sorted.size()-1) = count;
       return sorted[order-1];
    }
    

    更快吗?

    set.seed(42)
    x <- rnorm(20000)
    p <- rnorm(100)
    
    all.equal(countsmaller(x, p), 
              sapply(p, function(pi) sum(x <= pi)))
    #TRUE
    
    library(microbenchmark)
    microbenchmark(colSums(outer(x, p, "<=")), 
    sapply(p, function(pi) sum(x <= pi)),
    countsmaller(x, p)
    )
    
    # Unit: milliseconds
    #                                 expr       min        lq    median        uq        max neval
    #           colSums(outer(x, p, "<=")) 22.354525 64.833602 65.343129 66.161082 149.428049   100
    # sapply(p, function(pi) sum(x <= pi)) 12.922805 13.344871 14.444304 15.009727  58.607176   100
    #                   countsmaller(x, p)  1.650383  1.703044  1.730453  1.754937   2.222273   100
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 2020-01-01
      • 2017-03-18
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      相关资源
      最近更新 更多