I want to sum up/average the values for each key and create a new entry in the dataset, with APP key "Total" and then show all the summed/averaged values in the last row.
I believe the previous answers have misunderstood the question. If you want to create a new entry in your dataset which contains totals for some keys and averages for others, then my answer may help.
Start by defining sum and avg in terms of a collection of numbers. You can always improve the implementation of these functions later, so keep it simple for now.
(defn sum [coll] (reduce + coll))
;;(sum [1 2 3])
;;=> 6
(defn avg [coll] (/ (sum coll) (count coll)))
;;(avg [1 2 3])
;;=> 2
To avoid repeating yourself, define a function for reducing your 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)))
reduce-dataset expects val to be a map and dataset to be a collection of maps, like your dataset.
Use reduce-dataset to define totals and averages in terms of sum and avg.
(defn totals [dataset] (reduce-dataset sum {:APP "Totals"} dataset))
(defn averages [dataset] (reduce-dataset avg {:APP "Averages"} dataset))
Since you want to the total of some keys in your dataset and the average of others, you'll need a way to select just those keys across the dataset.
(defn select-cols [dataset ks] (map #(select-keys % ks) dataset))
Now you have everything you need to calculate totals and averages selectively across your 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"}
You can combine the results with your original dataset using conj.
(conj dataset
(totals (select-cols dataset [:Total :p1 :p2 :p3]))
(averages (select-cols dataset [:p1percent :p2percent :p3percent])))
This adds two rows to the dataset, one for totals and one for averages. To add a single row, you can merge the results before conj'ing.
(conj dataset
(merge (totals (select-cols dataset [:Total :p1 :p2 :p3]))
(averages (select-cols dataset [:p1percent :p2percent :p3percent]))
{:APP "Total/Avg"}))
In the case of conflicting keys, merge will always use the last value it sees, so in the example above, The value of :APP will be "Total/Avg" not "Totals" or "Averages".