HOWTO · NumPy

Python で NumPy 配列を CSV に書き込む

このチュートリアルでは、numpy 配列を csv ファイルに保存する方法を示します

このページの内容

数値を含むNumPy配列をカンマ区切りのテキストとして書き出すには、numpy.savetxt()を使います。DataFrameを使う処理の一環として保存する場合はpandasを、行を組み立てたりカスタマイズしたりする場合はcsv.writerを選びます。CSVは行と列でデータを表すため、1次元または高次元の配列をどのように行へ対応させるか、保存前に決めておきましょう。

例では、整数値を含む小さな2次元配列を使います。どの方法でも、ヘッダーやインデックスを付けず、値だけを書き出します。配列の例にはNumPyが必要です。pandasは追加パッケージで、該当する節の例を使う場合にのみ必要です。コードと表示されるラベルや出力は、変更していない例のまま英語です。

配列と必要な出力に応じて方法を選ぶ

数値配列をシンプルな区切りテキストファイルに保存するなら、numpy.savetxt()が手軽な標準の選択肢です。区切り文字はdelimiterで、各値の表記形式はfmtで指定します。DataFrameの操作や列ラベルが必要ならpandasを使います。行ごとの加工が必要な場合や、PythonのCSV用引用符処理を利用したい場合はcsv.writerを選びましょう。組み込みのwriterは、値を自分で文字列に連結する方法よりも、フィールド内のカンマや引用符を安全に処理できます。

savetxtは1次元配列を列ベクトルとして扱うため、1行につき1つの値を書き出します。値をCSVの1行に横並びで書きたい場合は、保存前に配列を(1, -1)へreshapeします。次のcsv.writerのループは2次元配列を前提としています。ループで取り出す各row自体が反復可能だからです。1次元の入力を1行に書くにはwriter.writerow(data)を使います。値を1つずつ別の行に書くには、値を反復してwriter.writerow([value])を呼び出します。CSVには3次元データをそのまま表す方法がありません。3次元配列は行と列にreshapeするか、flattenする必要があります。その際は、読み込み側で元の並びを再現できる順序を選びましょう。flattenした並びによってデータ配置が意図せず決まらないようにしてください。

numpy.savetxt()でNumPy配列を保存する

例の整数値には'%d'形式が適しています。浮動小数点データの場合、小数点以下3桁で十分なら'%.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")で開き、新しい行だけを書き込みます。列の順序と数が既存ファイルと一致していることを確認してください。追記モードは、内容の検証もヘッダーの追加も行いません。1次元の入力が1行を表すのか、1行につき1つの値を表すのかを決め、必要に応じてreshapeするか、値をリストで囲んでください。

ndarray.tofile()の制約を理解する

ndarray.tofile()は配列のメソッドですが、CSVライターではありません。配列の要素をflattenした順序で書き出すため、元のshapeや行と列の構造は保持されません。カンマ区切りにすれば区切りテキストは作れますが、ファイルから元の次元数は分かりません。また、出力の表現は選んだ形式によって変わります。1行に出力されることだけを理由に、数値の精度が失われたとはいえません。CSVのレイアウトを明示する必要がある場合は、savetxt、pandas、またはcsv.writerを使いましょう。

シンプルなデータに限ってCSVテキストを手動で書く

形が分かっている小さな2次元配列に単純な数値が含まれる場合は、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