Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对clojure中的值求和,并将总计添加到数据集_Clojure - Fatal编程技术网

对clojure中的值求和,并将总计添加到数据集

对clojure中的值求和,并将总计添加到数据集,clojure,Clojure,我是clojure的新手,我从xml文档中解析了以下数据集,并将其显示在excel文件中: ({:Total 28, :p3percent 89.28571428571429, :p2percent 0.0, :p1percent 10.71428571428571, :APP "A", :p1 3, :p2 0, :p3 25} {:Total 40, :p3percent 92.5, :p2percent 0.0, :p1percent 7.5, :APP "b", :p1 3, :p2

我是clojure的新手,我从xml文档中解析了以下数据集,并将其显示在excel文件中:

({:Total 28, :p3percent 89.28571428571429, :p2percent 0.0, :p1percent 10.71428571428571, :APP "A", :p1 3, :p2 0, :p3 25}
 {:Total 40, :p3percent 92.5, :p2percent 0.0, :p1percent 7.5, :APP "b", :p1 3, :p2 0, :p3 37} 
 {:Total 64, :p3percent 93.75, :p2percent 0.0, :p1percent 6.25, :APP "c", :p1 4, :p2 0, :p3 60} 
 {:Total 128, :p3percent 83.59375, :p2percent 12.5, :p1percent 3.90625, :APP "d", :p1 5, :p2 16, :p3 107}
 {:Total 6, :p3percent 83.33333333333333, :p2percent 16.66666666666667, :p1percent 0.0, :APP "e", :p1 0, :p2 1, :p3 5}
 {:Total 8, :p3percent 87.5, :p2percent 12.5, :p1percent 0.0, :APP "f", :p1 0, :p2 1, :p3 7})
我想对每个键的值进行求和/平均,并在数据集中创建一个新条目,使用APP key“Total”,然后在最后一行显示所有求和/平均值。这可以在excel中轻松完成,但我显然想先在clojure中完成

我知道如何获取每个键的总和,即(apply+map(:p1 dataset)),但如何创建一个函数来迭代数据集并将总计作为数据集中的一个额外行添加

谢谢

D

尝试功能。检查链接中的第二个示例。

我想这是你想要的。此函数将帮助您创建最后一行“总计”。唯一的问题是你有一个字段不是数字。因此,您可以将特殊函数传递给忽略字符串的
合并

如果您只是想生成一个包含对应键的总计或平均值的映射
reduce
可以很好地做到这一点:

user> (pprint (reduce #(assoc %2 :Total (+ (:Total %2) (:Total %1))) {:Total 0} data)) {:p1 0, :p3 7, :p2percent 12.5, :p2 1, :p1percent 0.0, :APP "f", :p3percent 87.5, :Total 274} nil 然后可以链接此函数,以汇总所需的键

user> (->> data 
        (sum-key :Total :Total-sum) 
        (sum-key :p1 :p1-sum) 
        (sum-key :p2 :p2-sum))
{:p1 0, :p2-sum 18, 
 :p3 7, :p2percent 12.5, 
 :p2 1, :p1percent 0.0, 
 :APP "f", :p3percent 87.5, 
 :Total 8}

如果您想要运行总计,则使用
减少值

我想对每个键的值进行求和/平均,并在数据集中创建一个新条目,使用APP key“Total”,然后在最后一行显示所有求和/平均值

我相信前面的回答误解了这个问题。如果您想在数据集中创建一个新条目,其中包含一些关键点的总计和其他关键点的平均值,那么我的答案可能会有所帮助


首先根据一组数字定义
sum
avg
。您可以随时在以后改进这些函数的实现,因此现在请保持简单

(defn sum [coll] (reduce + coll))
;;(sum [1 2 3])
;;=> 6
(defn avg [coll] (/ (sum coll) (count coll)))
;;(avg [1 2 3])
;;=> 2
为了避免重复,请定义一个函数来减少数据集

(defn dataset-keys [d] (reduce #(into %1 (keys %2)) #{} d))

(defn reduce-dataset
  [f val dataset]
  (reduce (fn [m k] (assoc m k (f (map k dataset))))
          val
          (dataset-keys dataset)))
(totals (select-cols your-dataset [:Total :p1 :p2 :p3]))
;;{:Total 274, :p2 18, :p3 241, :p1 15, :APP "Totals"}

(averages (select-cols your-dataset [:p1percent :p2percent :p3percent]))
;; {:p3percent 88.32713293650794, :p1percent 4.728422619047618, :p2percent 6.9444444444444455, :APP "Averages"}
reduce-dataset
期望
val
是一个映射,
dataset
是一个映射的集合,就像您的数据集一样

(defn dataset-keys [d] (reduce #(into %1 (keys %2)) #{} d))

(defn reduce-dataset
  [f val dataset]
  (reduce (fn [m k] (assoc m k (f (map k dataset))))
          val
          (dataset-keys dataset)))
(totals (select-cols your-dataset [:Total :p1 :p2 :p3]))
;;{:Total 274, :p2 18, :p3 241, :p1 15, :APP "Totals"}

(averages (select-cols your-dataset [:p1percent :p2percent :p3percent]))
;; {:p3percent 88.32713293650794, :p1percent 4.728422619047618, :p2percent 6.9444444444444455, :APP "Averages"}
使用
reduce dataset
sum
avg
的形式定义
totals
averages

(defn totals [dataset] (reduce-dataset sum {:APP "Totals"} dataset))
(defn averages [dataset] (reduce-dataset avg {:APP "Averages"} dataset))
由于要计算数据集中某些键的总数和其他键的平均数,因此需要一种方法来选择整个数据集中的那些键

(defn select-cols [dataset ks] (map #(select-keys % ks) dataset))
现在,您已经具备了在数据集中有选择地计算总计和平均值所需的一切

(defn dataset-keys [d] (reduce #(into %1 (keys %2)) #{} d))

(defn reduce-dataset
  [f val dataset]
  (reduce (fn [m k] (assoc m k (f (map k dataset))))
          val
          (dataset-keys dataset)))
(totals (select-cols your-dataset [:Total :p1 :p2 :p3]))
;;{:Total 274, :p2 18, :p3 241, :p1 15, :APP "Totals"}

(averages (select-cols your-dataset [:p1percent :p2percent :p3percent]))
;; {:p3percent 88.32713293650794, :p1percent 4.728422619047618, :p2percent 6.9444444444444455, :APP "Averages"}
您可以使用conj将结果与原始数据集相结合

(conj dataset
      (totals (select-cols dataset [:Total :p1 :p2 :p3]))
      (averages (select-cols dataset [:p1percent :p2percent :p3percent])))
这将向数据集中添加两行,一行用于总计,另一行用于平均值。要添加一行,可以在合并前合并结果

(conj dataset
      (merge (totals (select-cols dataset [:Total :p1 :p2 :p3]))
             (averages (select-cols dataset [:p1percent :p2percent :p3percent]))
             {:APP "Total/Avg"}))

在键冲突的情况下,
merge
将始终使用它看到的最后一个值,因此在上面的示例中,
:APP
的值将是
“总计/Avg”
而不是
“总计”
“平均值”

您好,感谢您的回复,我远离合并+因为我还想得到某些键的平均值和总和。。。我真的应该在最初的描述中提到,道歉。@Arthur_Ulfeldt什么时候使用reduce会因为实现整个序列而导致问题?我这样问是因为我会定期看到一些评论,指出为什么不应该使用reduce。tnxreduce生成一个结果,将您提供给它的所有数据缩减为一个值(因此它的名称),因此,如果您不希望它实现整个流,则使用(获取X数据)。Reduce不包含对惰性序列头部的引用,因此在比ram大的数据集上使用它是安全的。我编辑它是为了更好地匹配这个问题,我(我想)一开始误解了。听起来您需要在映射中保留原始数据,并添加包含平均值、总和等的新键。