我目前正在寻找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))))))))