Как я могу изменить столбец в наборе данных Incanter? - PullRequest
8 голосов
/ 30 марта 2011

Я хотел бы иметь возможность преобразовать отдельный столбец в наборе данных заклинателя и сохранить полученный набор данных в новый файл (CSV). Какой самый простой способ сделать это?

По сути, я хотел бы иметь возможность отобразить функцию на столбец в наборе данных и заменить исходный столбец этим результатом.

Ответы [ 4 ]

5 голосов
/ 03 августа 2011

Вот две аналогичные функции, как имя столбца, так и сохранение порядка.

(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 для случая, когда преобразование для одной строки зависит от других строк (например, при нормализации столбца).

Сохранение и загрузка CSV могут выполняться с помощью стандартных функций Incanter, поэтомуполный пример выглядит так:

(use '(incanter core io)))

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

(save (transform-rows :a #(* % 2) data) 'transformed-data.csv')
5 голосов
/ 30 марта 2011

Вы можете определить что-то вроде:

(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))

Существует только одна проблема с изменением имен столбцов - я постараюсь это исправить, когдаУ меня будет свободное время ...

2 голосов
/ 12 февраля 2014

ПРИМЕЧАНИЕ: для этого решения требуется Incanter 1.5.3 или выше

Для тех, кто может использовать последние версии Incanter ...

add-column & add-output-column были добавлены в Incanter в 1.5.3 (запрос на извлечение) )

Из документов:

добавить колонки

"Добавляет столбец с заданными значениями в набор данных."

(add-column column-name values)

или

(add-column column-name values data)

Или вы можете использовать:

добавить производные колонки

"Эта функция добавляет столбец в набор данных, который является функцией существующие столбцы. Если набор данных не предоставлен, $ data (связано с будет использоваться макрос с данными). F должно быть функцией от from-колонки с аргументами в таком порядке. "

(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 %))))
2 голосов
/ 30 марта 2011

Опять же: возможно, вы можете использовать внутреннюю структуру набора данных.

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.

...