Clojure 简单的;“类R”;融化:更好的方法吗?
今天我尝试实现一个“类似R”的熔化功能。我用它来处理来自大查询的大数据。 我对计算时间没有太大的限制,而且这个函数在数百万行上运行不到5-10秒 我从这类数据开始:Clojure 简单的;“类R”;融化:更好的方法吗?,clojure,reduce,melt,Clojure,Reduce,Melt,今天我尝试实现一个“类似R”的熔化功能。我用它来处理来自大查询的大数据。 我对计算时间没有太大的限制,而且这个函数在数百万行上运行不到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] (a
(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)
(split-melt sample :list)
正如您所看到的,它返回相同的序列,但它将:list替换为一个映射,该映射给出了引用列表中每个项目在列表中的位置
然后,我想通过为组中的每个项目创建其自己的行及其在组中的排名来融化“数据帧”
所以我创建了这个函数:
(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-data-rank sample :list)
(split-melt sample :list)
问题是它缩进严重,并且使用了大量的映射。我将dissoc应用于drop:list(现在已经没用了),我还必须使用concat,因为没有它,我就有一系列序列
您认为有没有更有效/更短的方法来设计此功能?
我对reduce非常困惑,不知道它是否可以在这里应用,因为在某种程度上有两个参数
非常感谢 如果您不需要
分割数据等级
功能,我会选择:
(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))
嵌套的
map
函数和许多匿名函数都是提示,这不是理想的Clojure。我不知道你打算怎么做,但我建议你先去看看。您是否绑定到该示例数据结构?为什么被引用?你想从中得到什么?接受两个参数的函数,传统上是累加器和值。还有一个函数,所以(apply concat)(map…)可以省略。因为您使用的是map,所以可以帮助您使用(map)(fn[k v]…有很多改进选项@dAni有一个很好的实现,如果你找到更好的方法,请发送一个pull请求到。感谢你的输入。Reduce kv似乎非常强大,我会考虑一下。像这样的嵌套贴图写和读起来都不是很好。我打算计算每个不同项目的平均等级,但我知道如何计算使用group by进行操作。我一定会使用这种引用的数据,特别是因为我从Google Big Query获取这些数据。非常感谢,好多了。我确实可以删除第一个函数,我使用了这个技巧,因为我不知道如何访问索引。我还在这里学习了两个有用的函数!