【发布时间】:2026-01-23 02:20:05
【问题描述】:
我目前正在研究 Clojure 和 Incanter 作为 R 的替代品。(不是我不喜欢 R,但尝试新语言很有趣。)我喜欢 Incanter,发现语法很吸引人,但矢量化操作相当比较慢,例如到 R 或 Python。
作为一个例子,我想得到一个向量的一阶差分 使用 Incanter 向量操作、Clojure 映射和 R 。以下是所有人的代码和时间 版本。如您所见,R 显然更快。
Incanter 和 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 中的向量操作?也欢迎使用 Clojure 中的循环、Java 数组和/或库的解决方案。
我也将这个问题发布到 Incanter Google 小组,目前没有任何回复。
更新:我已将 Jouni 的答案标记为已接受,请参阅下面的我自己的答案,我已经清理了他的代码并添加了一些基准。
【问题讨论】:
-
这会很困难,因为 R 的内在循环是用 C 或 Fortran 编程的。变得比这更快需要相当多的努力......
-
这和我之前的经验是一致的; Clojure 在基本操作上的速度几乎慢了 10 倍。我的建议:如果您正在寻找性能,请不要使用 Clojure;如果您想在 JVM 等上进行无缝集成,请使用它。您可能还会发现这个问题相关:*.com/questions/2186709/…。
-
rdiff 最好写成
x[-1] - x[-n]。 -
或
diff(已经存在)。例如,{ tmp <- rnorm(1e7); all(diff(tmp) == (tmp[-1]-tmp[-length(tmp)])) }#--> TRUE. -
@Matti 我可以理解你想比较相似的代码,但如果我比较语言,我会使用每种语言中最好的工具。就个人而言,我喜欢从柠檬中挤出最后一滴。