【问题标题】:Vectorize thinking向量化思维
【发布时间】:2015-09-03 10:45:28
【问题描述】:

我遇到了矢量化问题。假设我有一个向量x <- c(0,0,1,0,1,1,0),我想要的是得到向量(1,0,1,1),或者从第一个点到第一个非零点删除所有0,从最后一个非零点删除所有0到最后一个位置。在正常情况下这很容易,但棘手的部分是我不能使用任何循环(for、while 等)。基本上,我必须“矢量化”整个算法。有人帮忙吗?

【问题讨论】:

    标签: r vector vectorization


    【解决方案1】:

    好吧,如果速度是一个问题,只需使用循环:

    x <- rpois(1e8,1)
    # Zihu Guo & JacobH's answer
    system.time({zeros <- which(x > 0); x[zeros[1]:tail(zeros, n = 1)]})
    #    user  system elapsed 
    #    1.46    0.42    1.89 
    
    # a slightly improved version of their answer
    system.time({zeros <- which(!!x); x[zeros[1]:tail(zeros, n = 1)]})
    #    user  system elapsed 
    #    1.21    0.42    1.64 
    
    
    system.time({
        lo  = 0L
        lov = 0L
        while (!lov){ lo = lo+1L ; lov = lov+x[lo] }
        hi  = length(x)+1L
        hiv = 0L
        while (!hiv){ hi = hi-1L ; hiv = hiv+x[hi] }    
        x[lo:hi]
    })
    #    user  system elapsed 
    #    0.62    0.07    0.71 
    

    除了速度之外,这很好,因为它不需要真正的 R 知识。可能使用 Rcpp 包可以更快。

    (如果整个向量为零,这将永远不会终止。如果这很重要,可以进行小的调整。如果向量大部分为零,which 方法更快。例如,考虑x &lt;- rep(0L,1e8); x[1e8/2] &lt;- 1L。)

    【讨论】:

    • hmmm.. 我猜: 是瓶颈,可能seq.int 会更好。
    • @DavidArenburg 时间与我的 comp 上的更改相似。也许负索引更好......让我检查一下。
    • 这个想法:lo:hi 的构造可能比它的补充更昂贵。对于大多数 lamba = 1 的 rpois 样本,几乎没有任何内容被丢弃。
    • 伟大的例子弗兰克。您的方法更快的原因是,通常情况下循环遍历向量的第一个零条目比对整个向量执行向量化操作更快。情况并非总是如此。假设您有一个长度为 1e8 的向量,前 9e7 个条目为零。在这种情况下,我怀疑郭子虎的方法更快。因此,让您对问题的先验指导您的编程策略。
    • @JacobH 是的,好点。 x &lt;- rep(0L,1e8); x[1e8/2] &lt;- 1L 我的需要很长时间。
    【解决方案2】:

    我想你可以试试这个, 感谢@JacobH 的评论,这样会更快。

    x <- c(0,0,1,0,1,1,0)
    zeros <- which(x > 0)
    
    x[zeros[1]:tail(zeros, n = 1)]
    

    输出

    [1] 1 0 1 1

    【讨论】:

    • 对郭子虎的方法进行了微小的改变。初始化对其的调用。即zeros=which(x &gt; 0); x[zeros[1]:tail(zeros, n=1)]
    • 我的添加确实使它更具可读性。然而,它的重要性远不止于此。在@Zihu Guo 原帖中,哪个函数被调用了两次。这会导致不必要的计算。因此,我的添加将导致更快的代码。
    • @JacobH 谢谢你的评论,你是对的。我已经更改了代码。
    • @JacobH 你们可能对我刚刚添加的比较感兴趣(作为另一个答案)。 which 对于这个任务来说很慢,因为它会查看每个元素。在第一个非零结果处停止会更快。
    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 2015-09-07
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多