【问题标题】:Which is the more efficient way to accumulate a vector?哪种方法更有效地累积向量?
【发布时间】:2017-08-27 03:36:46
【问题描述】:

就完成时间而言,以下哪项更有效?

one.way = function(n) { if (n) c(n, one.way(n-1)) }
two.way = function(n) { if (n) c(two.way(n-1), n) }

这里的重点是单例向量与另一个长度可能大于一的向量的组合顺序。

如果您需要在使用上述函数之一构建向量后包含反转向量的时间,您的答案将如何变化?在组合时可能知道也可能不知道需要组合对象的顺序。

【问题讨论】:

  • 他们都超级慢,因为growing things without preallocating memory is slow。在这种情况下,seq: 会快得多。
  • 如前所述,“这里的重点在于将单个向量与另一个长度可能大于 1 的向量组合的顺序。”我给出了一个简单的例子,但许多其他情况也是可能的。
  • 我知道。重点是不要。取而代之的是向量化你的操作,或者至少预先分配一个适当长度的向量,否则 R 会变得非常缓慢。
  • 我是说不要递归/迭代地这样做;有更好的方法。如果你只做一次,你可以选择c(1, vec)c(vec, 1),这取决于你在输出中首先想要什么。
  • 是否有令人信服的理由采用递归/迭代方法?由于上面突出显示的问题,在 R 中通过循环迭代地做某事很少是问题的第一个答案。如果您觉得必须使用它,请详细说明您的情况并解释为什么其他方法不起作用。现在这听起来可能是XY problem

标签: r recursion vector accumulate


【解决方案1】:

回答你的问题,他们差不多

使用microbenchmark测试两个快速函数的性能

one.way = function(n) { c(n, 1) }
two.way = function(n) { c(1, n) }

n <- 2:100

library(microbenchmark)
microbenchmark(one.way(n), two.way(n), times=1e5)

#       expr   min    lq     mean median    uq      max neval
# one.way(n) 1.399 1.866 2.009775  1.867 1.867 2817.733 1e+05
# two.way(n) 1.399 1.866 2.086267  1.867 1.867 3394.808 1e+05

请注意,下四分位数、中位数和上四分位数都相同。手段略有不同,但并不重要。见下文

myfun <- function(n) {
              temp <- microbenchmark(one.way(n), two.way(n), times=1e5)
              df <- data.frame(one.way = mean(temp$time[temp$expr=="one.way(n)"]),
                           two.way = mean(temp$time[temp$expr=="two.way(n)"]))
              return(df)
     }

library(purrr)
test <- map_df(1:100, ~myfun(n))

t.test(test$one.way, test$two.way)

# data:  test$one.way and test$two.way
# t = -1.6506, df = 182.72, p-value = 0.1005
# alternative hypothesis: true difference in means is not equal to 0

【讨论】:

  • 虽然感谢其他线程关于厌恶递归的讨论,但我感谢您回答实际问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
相关资源
最近更新 更多