如何修改Incanter数据集中的列?

时间:2011-03-30 04:11:43

标签: clojure incanter

我希望能够转换incanter数据集中的单个列,并将结果数据集保存到新的(csv)文件中。最简单的方法是什么?

基本上,我希望能够在数据集中的列上映射函数,并用此结果替换原始列。

4 个答案:

答案 0 :(得分:5)

您可以定义类似的内容:

(defn map-data [dataset column fn]
  (conj-cols (sel dataset :except-cols column)
             ($map fn column dataset)))

并用作

(def data (get-dataset :cars))
(map-data data :speed #(* % 2))

更改列名只有一个问题 - 当我有空闲时间时,我会尝试修复它...

答案 1 :(得分:5)

以下是两个类似的功能,包括列名和保留顺序。

(defn transform-column [col-name f data] 
  (let [new-col-names (sort-by #(= % col-name) (col-names data))
        new-dataset (conj-cols
                      (sel data :except-cols col-name)
                      (f ($ col-name data)))]

    ($ (col-names data) (col-names new-dataset new-col-names) )))

(defn transform-rows [col-name f data] 
  (let [new-col-names (sort-by #(= % col-name) (col-names data))
        new-dataset (conj-cols
                      (sel data :except-cols col-name)
                      ($map f col-name data))]

这是一个说明差异的例子:

=> (def test-data (to-dataset [{:a 1 :b 2} {:a 3 :b 4}])) 
=> (transform-column :a (fn [x] (map #(* % 2) x)) test-data)
[:a :b]
[2 2]
[6 4]

=> (transform-rows   :a #(* % 2) test-data)
[:a :b]
[2 2]
[6 4]

transform-rows最适合简单转换,其中transform-column用于当一行的转换依赖于其他行时(例如对列进行规范化时)。

使用标准的Incanter功能可以保存和加载CSV,因此完整的示例如下所示:

(use '(incanter core io)))

(def data (col-names (read-dataset 'data.csv') [:a :b])

(save (transform-rows :a #(* % 2) data) 'transformed-data.csv')

答案 2 :(得分:2)

再次:也许您可以使用数据集的内部结构。

user=> (defn update-column
         [dataset column f & args]
         (->> (map #(apply update-in % [column] f args) (:rows dataset))
           vec
           (assoc dataset :rows)))
#'user/update-column
user=> d
[:col-0 :col-1]
[1 2]
[3 4]
[5 6]

user=> (update-column d :col-1 str "d")
[:col-0 :col-1]
[1 "2d"]
[3 "4d"]
[5 "6d"]

同样应该检查这是公共API的程度。

答案 3 :(得分:2)

注意:此解决方案需要Incanter 1.5.3或更高版本

对于那些可以使用最近版本的Incanter的人......

add-column & add-derived-column 已在1.5.3 (pull request)

中添加到Incanter

来自文档:

add-column

“将具有给定值的列添加到数据集中。”

(add-column column-name values)

(add-column column-name values data)

或者您可以使用:

add-derived-column

“此函数将列添加到作为其函数的数据集中 现有专栏。如果没有提供数据集,则为$ data(由...绑定) 将使用with-data宏)。 f应该是一个函数 from-columns,按顺序使用参数。“

(add-derived-column column-name from-columns f)

(add-derived-column column-name from-columns f data)

更完整的例子

(use '(incanter core datasets))
  (def cars (get-dataset :cars))

(add-derived-column :dist-over-speed [:dist :speed] (fn [d s] (/ d s)) cars)

(with-data (get-dataset :cars)
  (view (add-derived-column :speed**-1 [:speed] #(/ 1.0 %))))