我目前正在寻找Clojure和Incanter来替代R。(并不是我不喜欢R,但是尝试新语言只是有趣的事情。)我喜欢Incanter并发现语法吸引人,但是矢量化操作与之相比相当慢例如到R或Python。

举例来说,我想得到 vector 的一阶差
使用Incanter vector 运算,Clojure映射和R。以下是所有代码和时间安排
版本。如您所见,R明显更快。

魔咒和Clojure:

(use '(incanter core stats))
(def x (doall (sample-normal 1e7)))
(time (def y (doall (minus (rest x) (butlast x)))))
"Elapsed time: 16481.337 msecs"
(time (def y (doall (map - (rest x) (butlast x)))))
"Elapsed time: 16457.850 msecs"

R:
rdiff <- function(x){
   n = length(x)
   x[2:n] - x[1:(n-1)]}
x = rnorm(1e7)
system.time(rdiff(x))
   user  system elapsed
  1.504   0.900   2.561

所以我想知道是否有一种方法可以加快Incanter / Clojure中的 vector 运算?也欢迎涉及使用Clojure的循环,Java数组和/或库的解决方案。

我也将此问题发布到了Incanter Google小组,到目前为止没有任何回复。

更新:我已将Jouni的答案标记为已接受,请参阅以下我自己的答案,在其中我对他的代码进行了一些整理并添加了一些基准。

最佳答案

这是在我的系统上比您的R代码(YMMV)更快的Java数组实现。请注意启用反射警告,这是优化性能时必不可少的,并在y上重复输入类型提示(def上的一个似乎对设置没有帮助)并将所有内容强制转换为原始double值(dotimes确保我是一个原始的int)。

(set! *warn-on-reflection* true)
(use 'incanter.stats)
(def ^"[D" x (double-array (sample-normal 1e7)))

(time
 (do
   (def ^"[D" y (double-array (dec (count x))))
   (dotimes [i (dec (count x))]
     (aset ^"[D" y
       i
       (double (- (double (aget x (inc i)))
                  (double (aget x i))))))))

10-06 15:34