今天我尝试实现“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)
正如您所看到的,它返回相同的序列,但它将替换:list by map,给出引用列表中每个项目列表中的位置。
然后,我想通过为组中的每个项创建自己的行以及其在组中的排名来融合“数据帧”。
所以我创建了这个函数:
(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,因为没有它我会有一系列序列。
您认为设计此功能有更高效/更短的方式吗? 我对 reduce 感到很困惑,不知道是否可以在这里应用,因为在某种程度上有两个参数。
非常感谢!
答案 0 :(得分:1)
如果您不需要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))