简单 "R-like" 融化:更好的方法吗?

Simple "R-like" melt : better way to do?

今天我尝试实现一个 "R-like" 熔化函数。我将它用于来自 Big Query 的大数据。 我对计算时间没有很大的限制,这个函数只需不到 5-10 秒就可以处理数百万行。

我从这样的数据入手:

(def sample 
  '({:list "123,250" :group "a"} {:list "234,260" :group "b"}))

然后我定义了一个函数来将列表放入向量中:

(defn split-data-rank [datatab value]
  (let [splitted (map (fn[x] (assoc x value (str/split (x value) #","))) datatab)]
    (map (fn[y] (let [index (map inc (range (count (y value))))] 
                  (assoc y value (zipmap index (y value))))) 
         splitted)))

启动:

(split-data-rank sample :list)

如您所见,它 returns 相同的序列,但它用地图替换了 :list ,给出了引用列表中每个项目在列表中的位置。

然后,我想通过为组中的每个项目创建自己的行及其在组中的排名来融化 "dataframe"。

所以我创建了这个函数:

(defn split-melt [datatab value]
  (let [splitted (split-data-rank datatab value)]
    (map (fn [y] (dissoc y value))
      (apply concat
        (map
          (fn[x]
            (map
              (fn[[k v]]
                (assoc x :item v :Rank k))
              (x value)))
     splitted)))))

启动:

(split-melt sample :list)

问题是它缩进很重并且使用了很多地图。我将 dissoc 应用于 drop :list (现在没用了),我还必须使用 concat 因为没有它我有一个序列序列。

你觉得有没有更efficient/shorter的方法来设计这个功能? 我对 reduce 很困惑,不知道它是否可以在这里应用,因为在某种程度上有两个参数。

非常感谢!

如果你不需要split-data-rank功能,我会选择:

(defn melt [datatab value]
  (mapcat (fn [x]
            (let [items (str/split (get x value) #",")]
              (map-indexed (fn [idx item]
                             (-> x
                                 (assoc :Rank (inc idx) :item item)
                                 (dissoc value)))
                           items)))
          datatab))