【问题标题】:In clojure, what is an efficient way to calculate average of integer vectors在clojure中,计算整数向量平均值的有效方法是什么
【发布时间】:2012-01-02 14:04:35
【问题描述】:

我有:

(def data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]])

我想平均这些(按元素获取):

[3 6 5 5 6]

就像在 MATLAB 中一样:

mean([1 3 4 7 9; 7 6 3 2 7; 1 9 8 6 2])

有了 Incanter,我可以做到:

(map #(/ % (count m)) (apply plus data))

如果数据相当大(而且我有很多),有没有更好的方法来做到这一点?
事先计算(count m) 有帮助吗?
事先对defn#(/ % (count m)) 有帮助吗?

【问题讨论】:

    标签: matlab clojure


    【解决方案1】:

    截至 2013 年,我的建议是只使用 core.matrix.stats 来导入所有这些功能:

    (mean [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]])
    => [3.0 6.0 5.0 5.0 6.0]
    

    core.matrix.stats 建立在 core.matrix API 之上,因此它也适用于其他更优化的向量和矩阵实现 - 如果您正在执行大量繁重的矩阵处理,这可能是一个更好的选择。

    【讨论】:

      【解决方案2】:

      这是一个非常干净和简单的方法:

      (def data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]])
      
      (defn average [coll] 
        (/ (reduce + coll) (count coll)))
      
      (defn transpose [coll]
         (apply map vector coll))
      
      (map average (transpose data))
      => (3 6 5 5 6)
      

      【讨论】:

      • 问自己 (apply + coll) 是否会比 (reduce + coll) 更有效率。已经在stackoverflow.com/questions/3153396/clojure-reduce-vs-apply回复了
      • Reduce 稍微快一点(在我刚刚完成的非正式测试中大约 5-10%)。但这实际上取决于个人喜好 - 我倾向于在归约操作中比在参数杂耍中更容易思考。
      【解决方案3】:

      在不知道如何使用任何 incanter 的情况下,以下是您可以“从头开始”执行此操作的方法。

      (let [data [[1 3 4 7 9] [7 6 3 2 7] [1 9 8 6 2]]
            num (count data)]
        (apply map (fn [& items]
                     (/ (apply + items) num))
               data))
      
      ;=> (3 6 5 5 6)
      

      【讨论】:

      • 谢谢@amalloy 它可以工作,但我不明白(apply map (fn ... 是如何工作的,不应该是(apply (map (fn ... 吗?
      • @Ali 不,您将map 函数应用于一系列参数:我们构造一个匿名函数,然后是data 序列的每个元素。 map 愿意接受“额外”参数,将它们传递给函数。例如,(map + [1 2] [10 20]) ~= [(+ 1 10) (+ 2 20)]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多