【问题标题】:Simple "R-like" melt : better way to do?简单的“R-like”融化:更好的方法是什么?
【发布时间】:2016-04-09 15:01:52
【问题描述】:

今天我尝试实现一个“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 替换为一个映射,给出引用列表中每个项目在列表中的位置。

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

所以我创建了这个函数:

(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 很困惑,不知道它是否可以在这里应用,因为在某种程度上有两个参数。

非常感谢!

【问题讨论】:

  • 嵌套的 map 函数和大量匿名函数表明这不是理想的 Clojure。我不确定您打算如何处理,但我建议您以 map-indexed 为起点。您是否绑定到该示例数据结构?为什么被引用?你想从中返回什么?
  • Reduce 采用两个参数的函数,传统上是累加器和值。还有一个 mapcat 函数,所以 (apply concat (map... 可以省略。由于您正在使用地图 reduce-kv 可以帮助您 (map (fn [kv]...为了改进@dAni 有一个很好的实现,如果你找到更好的方法,请发送请求到Incanter
  • 感谢您的意见。 reduce-kv 好像真的很强大,会考虑的。像这样的嵌套地图是不是很好写和读。我打算计算每个不同项目的平均排名,但我知道如何使用 group-by。我受制于这种引用数据,尤其是因为我从 Google Big Query 中获取它。

标签: clojure reduce melt


【解决方案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))

【讨论】:

  • 非常感谢,好多了。我确实可以删除第一个函数,我使用这个技巧是因为我不知道如何访问索引。在这里我也学到了两个有用的功能!
猜你喜欢
  • 1970-01-01
  • 2014-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多