简单 "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))
今天我尝试实现一个 "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))