You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clojure使用clojure.data.csv解析CSV为向量映射速度过慢求助

优化Clojure CSV解析性能的方案

原代码的问题分析

  • 惰性序列的低效处理:csv/read-csv返回惰性序列,rest in-file同样是惰性的,执行apply mapv vector data时会强制将所有行一次性加载到内存,对于大文件来说会产生大量内存开销,拖慢处理速度。
  • 未完成数值转换:原代码直接保留CSV中的字符串值,没有转换为你需要的数值类型,后续使用时还会额外消耗性能。
  • 转置操作效率低下:apply mapv vector的转置方式需要先把所有行读入内存再进行列重组,对于行数较多的文件来说是低效的。

重构后的代码

(require '[clojure.data.csv :as csv]
         '[clojure.java.io :as io])

(defn parse-number [s]
  (when (seq s)
    (try
      (Double/parseDouble s)
      (catch NumberFormatException _ nil))))

(defn csv->df [file-path]
  (with-open [reader (io/reader file-path :encoding "UTF-8")]
    (let [csv-data (csv/read-csv reader)
          headers (map keyword (first csv-data))
          initial-df (zipmap headers (repeat []))]
      (reduce (fn [df row]
                (let [values (map parse-number row)]
                  (merge-with into df (zipmap headers (map vector values)))))
              initial-df
              (rest csv-data)))))

;; 调用示例
(csv->df "data/flights.csv")

优化点说明

  • 边读边处理:使用reduce遍历每一行数据,逐步构建列向量,不需要一次性加载所有行到内存,内存占用更低,处理速度更快。
  • 数值转换:新增parse-number函数将CSV中的字符串转换为Double类型,同时处理空值和格式错误的情况,符合你需要数值向量的需求。
  • 指定编码:显式指定文件编码为UTF-8,避免默认编码检测的额外开销。
  • 惰性序列合理消费:reduce会逐个消费csv/read-csv返回的惰性序列,不会产生不必要的内存堆积。

额外性能建议

  • 如果文件行数极多,可以考虑使用pmap并行处理行数据,但注意并行处理会增加内存开销,需要根据实际情况权衡。
  • 若不需要保留所有列,可以在遍历前过滤掉不需要的表头,减少后续处理的数据量。

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:22:43