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,我有一个从数据库返回的地图集合,数据布局如下 [{:date "2012-6-6" :region "US" :status 1} {:date "2012-6-10" :region "UK" :status 2} {:date "2012-6-10" :region "US" :status 1} {:date "2012-6-11" :region "UK" :status 3}] 我想对数据进行透视/转置,以便 [{:date "2012-6-6" :US 1 :UK 0} {

我有一个从数据库返回的地图集合,数据布局如下

[{:date "2012-6-6" :region "US" :status 1}
 {:date "2012-6-10" :region "UK" :status 2}
 {:date "2012-6-10" :region "US" :status 1}
 {:date "2012-6-11" :region "UK" :status 3}]
我想对数据进行透视/转置,以便

[{:date "2012-6-6" :US 1 :UK 0}
 {:date "2012-6-10" :US 1 :UK 2}
 {:date "2012-6-11" :US 0 :UK 3}]

这不能处理缺少区域需要零的情况

(->> (group-by :date DB-DATA)
     (map (fn [[_ coll]]
            (apply merge (map (fn [{:keys [status date region]}]
                                {:date date (keyword region) status})
                              coll))))
     vec)
=> [{:date "2012-6-6", :US 1} {:US 1, :date "2012-6-10", :UK 2} {:date "2012-6-11", :UK 3}]

这不能处理缺少区域需要零的情况

(->> (group-by :date DB-DATA)
     (map (fn [[_ coll]]
            (apply merge (map (fn [{:keys [status date region]}]
                                {:date date (keyword region) status})
                              coll))))
     vec)
=> [{:date "2012-6-6", :US 1} {:US 1, :date "2012-6-10", :UK 2} {:date "2012-6-11", :UK 3}]

下面是一种解决此问题的方法,如中所述,没有任何一般性:

(def data
  [{:date "2012-6-6" :region "US" :status 1}
   {:date "2012-6-10" :region "UK" :status 2}
   {:date "2012-6-10" :region "US" :status 1}
   {:date "2012-6-11" :region "UK" :status 3}]

=> (map (fn [[date data-points]]
          (apply assoc {:date date}
                 (mapcat (juxt (comp keyword :region)
                               :status)
                         data-points)))
        (group-by :date
                  data)))
=> ({:US 1, :date "2012-6-6"}
    {:US 1, :UK 2, :date "2012-6-10"}
    {:UK 3, :date "2012-6-11"})
它的工作原理是按日期对数据进行分组,然后映射一个函数(稍后我将讨论该函数)
group by
通过对元素调用某个函数并对该函数返回值相等的元素进行分组,从而按顺序对元素进行分组。它生成一个哈希映射,其中每个唯一的返回值都是一个键,映射中的每个值都是返回该值的原始序列中的元素序列。例如,以下是按日期分组的数据:

{"2012-6-6" [{:status 1
              :date "2012-6-6"
              :region "US"}]
 "2012-6-10" [{:status 2
               :date "2012-6-10"
               :region "UK"}
              {:status 1
               :date "2012-6-10"
               :region "US"}]
 "2012-6-11" [{:status 3
               :date "2012-6-11"
               :region "UK"}]}
这就是分组方式的工作原理。现在,映射到此分组数据的函数将
date
绑定到每个序列的第一个元素,并将
数据点
绑定到每个序列的第二个元素。我们将
(将assoc{:date}…
应用于数据点的“重组”,其中
:region
处的值现在是
:status
处值的关键字。“重组”是通过使用调用每个数据点上的
(comp关键字:region)
:status
的函数来实现的

为了有希望地阐明这个
juxt
-ed函数的作用,我给出了如果写出它的等价物的样子:

(defn above-juxted-fn
  [data-point]
  [(keyword (:region data-point))
   (:status data-point)])
现在,实际上这不是一个完整的解决方案,因为您似乎希望将所有可能的区域都包含为关键字,如果没有该区域和日期的数据,则该值为零。但是,根据上述解决方案返回的结果,无论何时对任何数据点执行
(此处获取区域键)
,您都可以执行
(此处获取区域键0)
,因此,如果查找未找到给定区域键,则默认值为零

另一件事:如果你正在处理大量数据,我不相信这是一种特别快速的做事方式(也许其他人会在这里得到更准确和详细的建议)。我写它的目的是为了简单和简约

此外,正如我上面所说,它没有一般性。至于一般性,我们可以通过将其建模为一个函数来改变它,该函数包含三个参数:1)一系列映射2)一个分组键和3)一系列“new key at”“new val at”对,我称之为重构规范(例如,在上面,这将是
[:region:status]
)。下面是:

(defn group-and-restructure
  [data grouping-key & restructuring-specs]
  (let [grouped-data (group-by grouping-key
                               data)
        restructuring-fn (apply juxt
                                (mapcat (fn [[k1 k2]]
                                          [(comp keyword k1)
                                           k2])
                                        restructuring-specs))]
    (map (fn [[grouping-k-value
               data-points]]
           (apply assoc {grouping-key grouping-k-value}
                  (mapcat restructuring-fn
                          data-points)))
         grouped-data)))

=> (group-and-restructure
     [{:date "2012-6-6" :region "US" :status 1}
      {:date "2012-6-10" :region "UK" :status 2}
      {:date "2012-6-10" :region "US" :status 1}
      {:date "2012-6-11" :region "UK" :status 3}]
     :date
     [:region :status])
=> ({:US 1, :date "2012-6-6"}
    {:US 1, :UK 2, :date "2012-6-10"}
    {:UK 3, :date "2012-6-11"})
这与上面的特定解决方案非常相似。主要区别在于,重组规范被转换成一个函数,当
mapcat
-ted down
数据点时,该函数将返回一个新的键/val对序列,以
关联到新的返回数据中。最好的部分是,此功能允许您灵活地重新构造数据。例如,您可以按
:region
分组,并按
[:date:status]
重组,如下所示:

=> (group-and-restructure
     [{:date "2012-6-6" :region "US" :status 1}
      {:date "2012-6-10" :region "UK" :status 2}
      {:date "2012-6-10" :region "US" :status 1}
      {:date "2012-6-11" :region "UK" :status 3}]
     :region
     [:date :status])
=> ({:2012-6-10 1, :2012-6-6 1, :region "US"}
    {:2012-6-11 3, :2012-6-10 2, :region "UK"})

下面是一种解决此问题的方法,如中所述,没有任何一般性:

(def data
  [{:date "2012-6-6" :region "US" :status 1}
   {:date "2012-6-10" :region "UK" :status 2}
   {:date "2012-6-10" :region "US" :status 1}
   {:date "2012-6-11" :region "UK" :status 3}]

=> (map (fn [[date data-points]]
          (apply assoc {:date date}
                 (mapcat (juxt (comp keyword :region)
                               :status)
                         data-points)))
        (group-by :date
                  data)))
=> ({:US 1, :date "2012-6-6"}
    {:US 1, :UK 2, :date "2012-6-10"}
    {:UK 3, :date "2012-6-11"})
它的工作原理是按日期对数据进行分组,然后映射一个函数(稍后我将讨论该函数)
group by
通过对元素调用某个函数并对该函数返回值相等的元素进行分组,从而按顺序对元素进行分组。它生成一个哈希映射,其中每个唯一的返回值都是一个键,映射中的每个值都是返回该值的原始序列中的元素序列。例如,以下是按日期分组的数据:

{"2012-6-6" [{:status 1
              :date "2012-6-6"
              :region "US"}]
 "2012-6-10" [{:status 2
               :date "2012-6-10"
               :region "UK"}
              {:status 1
               :date "2012-6-10"
               :region "US"}]
 "2012-6-11" [{:status 3
               :date "2012-6-11"
               :region "UK"}]}
这就是分组方式的工作原理。现在,映射到此分组数据的函数将
date
绑定到每个序列的第一个元素,并将
数据点
绑定到每个序列的第二个元素。我们将
(将assoc{:date}…
应用于数据点的“重组”,其中
:region
处的值现在是
:status
处值的关键字。“重组”是通过使用调用每个数据点上的
(comp关键字:region)
:status
的函数来实现的

为了有希望地阐明这个
juxt
-ed函数的作用,我给出了如果写出它的等价物的样子:

(defn above-juxted-fn
  [data-point]
  [(keyword (:region data-point))
   (:status data-point)])
现在,实际上这不是一个完整的解决方案,因为您似乎希望将所有可能的区域都包含为关键字,如果没有该区域和日期的数据,则该值为零。但是,根据上述解决方案返回的结果,无论何时对任何数据点执行
(此处获取区域键)
,您都可以执行
(此处获取区域键0)
,因此,如果查找未找到给定区域键,则默认值为零

另一件事:如果你正在处理大量数据,我不相信这是一种特别快速的做事方式(也许其他人会在这里得到更准确和详细的建议)。我写它的目的是为了简单和简约

此外,正如我上面所说,它没有一般性。至于一般性,我们可以通过将其建模为一个函数来改变它,该函数包含三个参数:1)一系列映射2)一个分组键和3)一系列“new key at”“new val at”对,我称之为重构规范(例如,在上面,这将是
[:region:status]
)。下面是:

(defn group-and-restructure
  [data grouping-key & restructuring-specs]
  (let [grouped-data (group-by grouping-key
                               data)
        restructuring-fn (apply juxt
                                (mapcat (fn [[k1 k2]]
                                          [(comp keyword k1)
                                           k2])
                                        restructuring-specs))]
    (map (fn [[grouping-k-value
               data-points]]
           (apply assoc {grouping-key grouping-k-value}
                  (mapcat restructuring-fn
                          data-points)))
         grouped-data)))

=> (group-and-restructure
     [{:date "2012-6-6" :region "US" :status 1}
      {:date "2012-6-10" :region "UK" :status 2}
      {:date "2012-6-10" :region "US" :status 1}
      {:date "2012-6-11" :region "UK" :status 3}]
     :date
     [:region :status])
=> ({:US 1, :date "2012-6-6"}
    {:US 1, :UK 2, :date "2012-6-10"}
    {:UK 3, :date "2012-6-11"})
这与上面的特定解决方案非常相似。主要区别在于,重组规范转换为一个函数,当
mapcat
-t