HOWTO · NumPy

在 Python 中将 NumPy 数组写入 CSV

本教程演示如何将 numpy 数组保存在 csv 文件中

本页内容

使用 numpy.savetxt() 可以将数值型 NumPy 数组写成以逗号分隔的文本。如果数组已经属于 DataFrame 工作流,可选择 pandas;如果需要构建或自定义行,可使用 csv.writer。CSV 由行和列组成,因此保存前应先确定一维或更高维数组如何映射到这些行列中。

示例使用一个包含整数的小型二维数组。每种方法都只写入数值,不包含表头或索引。数组示例需要 NumPy;pandas 是额外安装的程序包,仅在对应章节中需要。

根据数组和所需输出选择方法

对于数值数组和简单的分隔文本文件,numpy.savetxt() 是直接实用的默认选择。它的 delimiter 用于设置分隔符,fmt 用于控制每个值的表示格式。如果你已经需要 DataFrame 操作或列标签,可以使用 pandas。如果需要自定义处理行,或需要遵循 Python 的 CSV 转义规则,可以使用 csv.writer。与自行将值拼接成字符串相比,内置写入器能更安全地处理字段中的逗号和引号。

numpy.savetxt() 会将一维数组视为列向量,因此默认每行写入一个值。若要将这些值写在 CSV 的同一行中,保存前先将数组重塑为 (1, -1)。下面的 csv.writer 循环假定数组是二维的:每次迭代得到的 row 本身都是可迭代对象。对于一维输入,可以使用 writer.writerow(data) 写入一行;也可以逐个遍历数值,并调用 writer.writerow([value]),让每个值各占一行。CSV 没有原生的三维表示方式。可以将三维数组重塑为行列结构,或将其展平;选择一种读取端能够还原的顺序,不要让展平过程在不知不觉中决定数据布局。

使用 numpy.savetxt() 保存 NumPy 数组

示例中的整数适合使用 '%d' 格式。对于浮点数据,如果保留小数点后三位已经足够,可以选择 '%.3f' 这样的格式;格式化可能会对数值进行舍入,因此应根据需要保留的数据精度选择格式。接收工具需要其他分隔符时,也可以将 ';' 或 '\\t' 等值传给 delimiter。

运行此示例。示例中的代码以及可见标签和输出保持英文;本节文字说明了其用途和行为。

本节中的代码以及显示的标签或输出仍为英文。

from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np

data = np.array([[1, 2, 3], [4, 5, 6]])
with TemporaryDirectory() as directory:
    path = Path(directory) / "array.csv"
    np.savetxt(path, data, delimiter=",", fmt="%d")
    print(path.read_text(), end="")
1,2,3
4,5,6

使用 pandas 保存 NumPy 数组

先将数组转换为 DataFrame,再调用 to_csv()。默认情况下,pandas 会写入 DataFrame 的索引和列名;如果文件只应包含数组值,请设置 index=False 和 header=False。如果索引或列名对接收者有意义,则可以保留或提供这些字段。此处示例中的代码及其可见标签和输出保持英文。

本节中的代码以及显示的标签或输出仍为英文。

from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np
import pandas as pd

data = np.array([[1, 2, 3], [4, 5, 6]])
with TemporaryDirectory() as directory:
    path = Path(directory) / "array.csv"
    pd.DataFrame(data).to_csv(path, index=False, header=False)
    print(path.read_text(), end="")
1,2,3
4,5,6

使用 Python 的 csv 模块写入行

csv.writer 会写入每个可迭代的行,并在 CSV 语法需要时对字段进行转义。打开文件时使用 newline="";这样换行符由 CSV 模块处理,可避免在进行换行转换的平台上出现多余空行。下面的示例直接使用数组中的各行。示例代码及其可见标签和输出保持英文。

本节中的代码以及显示的标签或输出仍为英文。

from pathlib import Path
from tempfile import TemporaryDirectory
import csv
import numpy as np

data = np.array([[1, 2, 3], [4, 5, 6]])
with TemporaryDirectory() as directory:
    path = Path(directory) / "array.csv"
    with path.open("w", newline="", encoding="utf-8") as file:
        writer = csv.writer(file)
        for row in data:
            writer.writerow(row)
    print(path.read_text(), end="")
1,2,3
4,5,6

要追加行,请以追加模式 ("a") 打开目标文件,并且只写入新增行。请确保新增行的列顺序和列数与现有内容一致;追加模式不会替你检查这些内容,也不会自动添加表头。对于一维输入,应先决定它代表一行还是每行一个值,再相应地重塑或包装数据。

了解 ndarray.tofile() 的限制

ndarray.tofile() 是数组方法,但它不是 CSV 写入器。它会按展平后的顺序写入数组元素,不会保留原始形状或行列结构。使用逗号分隔符可以生成分隔文本,但文件仍无法告诉读取者数组原来的维度。输出表示形式还取决于所选格式;仅仅写成一行并不意味着数值精度已经丢失。需要明确 CSV 布局时,应优先使用 savetxt、pandas 或 csv.writer。

仅对简单数据手动写入 CSV 文本

对于已知形状、包含简单数值的小型二维数组,可以使用 Python 字符串格式化直接生成各行。这种方法假定数组的形状和值适合写成纯文本。使用 join 构建完整结果时,内存占用会随输出大小增长;手动拼接也不会按照 CSV 规则处理包含逗号、引号或换行符的值。一般数据或文本字段应使用 csv.writer。此处示例中的代码及其可见标签和输出保持英文。

本节中的代码以及显示的标签或输出仍为英文。

from pathlib import Path
from tempfile import TemporaryDirectory

data = [[1, 2, 3], [4, 5, 6]]
with TemporaryDirectory() as directory:
    path = Path(directory) / "array.csv"
    content = "\n".join(",".join(str(value) for value in row) for row in data)
    path.write_text(content + "\n", encoding="utf-8")
    print(path.read_text(), end="")
1,2,3
4,5,6