NumPy 的 loadtxt 和 genfromtxt 不适合加载 GB 级 CSV,因其逐行解析、无类型预设、不支持 chunk 且对混合类型/缺失值脆弱;推荐改用 pandas.read_csv 并转为 NumPy 数组。

numpy.loadtxt 和 numpy.genfromtxt 本身就不适合加载 GB 级 CSV —— 它们是为小规模、结构规整的数值矩阵设计的,遇到混合类型、缺失值、字符串列或百万行以上数据时,速度会断崖式下降,甚至比 pandas.read_csv 还慢。
真正要解决“NumPy 加载大型 CSV 慢”,第一步是确认:你真的需要用 NumPy 直接读 CSV 吗?
如果不是必须用纯 NumPy 数组(比如后续只做向量化数学运算且全为数值),那直接换回 pandas.read_csv 并针对性优化,效率和可控性都远超 NumPy 原生函数。
为什么 numpy.loadtxt 在大 CSV 上特别慢?
它默认逐行解析、不做类型预设、不跳过非数值内容、不支持 chunk、对空值/字符串/编码异常极其脆弱。一旦 CSV 里有任意一列含字符串或缺失,genfromtxt 就会退化成 object dtype + Python 层循环,100 万行可能耗时数分钟。
立即学习“Python免费学习笔记(深入)”;
常见错误现象:
-
TypeError: float() argument must be a string or a real number—— 遇到空单元格或文本就崩 - 内存占用飙升至文件体积 5–8 倍 —— object 数组 + Python 字符串开销
- 读取 50MB CSV 耗时 >30 秒,而
pandas.read_csv同配置只要 2 秒
替代方案:用 pandas.read_csv 但输出 NumPy 数组
多数场景下,你真正需要的是「最终得到一个 NumPy 数组」,而不是「非得用 NumPy 函数读」。这时最稳的路径是:
- 用
pandas.read_csv高效加载(指定dtype、usecols、chunksize) - 对目标数值列调用
.to_numpy(dtype=...)或.values - 避免
df.values返回 object 数组 —— 先确保列 dtype 是float32或int64
示例:
import pandas as pd
# 只读两列数值,强制类型,跳过 BOM
df = pd.read_csv("large.csv",
usecols=["price", "quantity"],
dtype={"price": "float32", "quantity": "int32"},
encoding="utf-8-sig")
arr = df.to_numpy() # shape (N, 2), dtype=float32/int32 混合 → 实际返回 object;改用:
arr_price = df["price"].to_numpy(dtype="float32")
arr_qty = df["quantity"].to_numpy(dtype="int32")真要用 NumPy,只能上 numpy.memmap + 手动解析
仅适用于:纯数值、固定宽度、无 header、无缺失、已知行列数的 CSV(本质是类二进制格式)。否则得自己写 Cython 或用 csv 模块流式转 numpy.ndarray,工程成本远高于换工具。
关键限制:
-
numpy.memmap不支持 CSV 格式,只支持二进制 flat 文件(如.npy或自定义二进制 layout) - 想用 memmap,得先用
pandas或csv把 CSV 转成二进制 → 这步本身就耗时,且失去“边读边算”的流式优势 - 实际项目中,99% 的“NumPy 读 CSV 慢”问题,根源是误选了函数,而非 NumPy 本身性能差
写入端也容易踩坑:numpy.savetxt 不适合大文件
它内部是 Python 循环 + 字符串格式化,写 100 万行常比 pd.DataFrame.to_csv 慢 3–5 倍,且不支持压缩、分块、多线程。
正确做法:
- 若需 NumPy 数组 →
pd.DataFrame(arr).to_csv(..., index=False) - 若坚持用 NumPy 写,优先考虑
numpy.save/numpy.savez(二进制,快且紧凑),而非 CSV - 必须输出 CSV?用
csv.writer流式写入,配合buffered=True和newline=""
真正的瓶颈往往不在“NumPy 快不快”,而在“是否在用正确的工具做正确的事”。把 CSV 当纯数值矩阵硬塞给 loadtxt,就像拿螺丝刀拧螺母——不是刀不行,是工具没对准任务。


















