pandas

【pandas】CSVファイルの入出力

【pandas】CSVファイルの入出力
naoki-hn

pandas の DataFrame で CSV ファイルを入出力する方法について解説します。

DataFrame の CSV ファイル入出力

CSV ファイルは、カンマで区切られたテキストファイルで各種データ保存に広く使用されています。Python では、CSV ファイルを扱うための csv モジュールが標準で用意されており、簡単に CSV ファイルの入出力が可能です。

しかし、データ分析では、pandas で用意されている DataFrameを使って操作する方が便利です。

この記事では、pandas の DataFrame で CSVファイルを入出力する方法について説明します。

CSV ファイルの読み込み read_csv

基本的な読み込み方法

CSV ファイルの読み込みには、pandas の read_csv 関数を使用します。ここでは以下の testdata.csv ファイルを例に基本的な読み込み方法を紹介します。

id,data,text,update_datetime
1,100,sample1,2022/1/1 9:00
2,200,sample2,2022/1/15 0:00
3,300,sample3,2022/2/1 9:00
4,400,sample4,2022/2/15 5:00
5,500,sample5,2022/2/28 0:00

CSV ファイルを DataFrame に読み込むには、read_csv 関数を使用します。

import pandas as pd

# CSVファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

print(df, "\n")
print(df.dtypes)
【実行結果】
   id  data     text update_datetime
0   1   100  sample1   2022/1/1 9:00
1   2   200  sample2  2022/1/15 0:00
2   3   300  sample3   2022/2/1 9:00
3   4   400  sample4  2022/2/15 5:00
4   5   500  sample5  2022/2/28 0:00 

id                  int64
data                int64
text               object
update_datetime    object
dtype: object

read_csv の引数にはファイルパスを指定します。文字コードは、encoding= で指定可能で、一般的には "utf-8" を使用しますが、場合によっては、"cp932"(Windows の日本語環境で一般的)を使用することもあります。適切なエンコーディング指定は、文字化けを防ぐために重要であるため状況により確認して使用してください。

読み込んだ CSV ファイルは DataFrame として取り込まれ、dtypes プロパティで列のデータ型を確認できます。この例では、iddataint64textupdate_datetimeobject として取り込まれています。

インデックスとなる列を指定して読み込む方法 index_col 引数

インデックス列を指定して CSV ファイルを読み込むには、read_csv 関数の index_col 引数を使用します。この引数には、インデックスとして使用する列名または列番号を指定できます。

特定の列を指定する場合
import pandas as pd

# インデックス列を指定して読み込む ※index_col=0のように列番号でも同じ
df = pd.read_csv("testdata.csv", encoding="utf-8", index_col="id")

print(df, "\n")
print(df.index, "\n")
print(df.dtypes)
【実行結果】
    data     text update_datetime
id                               
1    100  sample1   2022/1/1 9:00
2    200  sample2  2022/1/15 0:00
3    300  sample3   2022/2/1 9:00
4    400  sample4  2022/2/15 5:00
5    500  sample5  2022/2/28 0:00 

Int64Index([1, 2, 3, 4, 5], dtype='int64', name='id') 

data                int64
text               object
update_datetime    object
dtype: object

上記では、index_col 引数で id 列を指定しています。結果は、id 列が Int64Index として設定されています。なお、「index_col=0」のように列番号で指定も可能です。

階層インデックス (MultiIndex) として指定する場合

データによっては以下のような階層的インデックス構造を持っている CSV ファイルもあります。以下は、level1level2 の順で階層になっている CSV ファイルです。

level1,level2,data,text,update_datetime
1,1,100,sample1,2022/1/1 9:00
1,2,200,sample2,2022/1/15 0:00
1,3,300,sample3,2022/2/1 9:00
2,1,400,sample4,2022/2/15 5:00
2,2,500,sample5,2022/2/28 0:00

このような階層的なインデックスを持つ CSV ファイルに対しては、以下のように index_col に複数列をレベル順にリスト指定することで対応できます。

import pandas as pd

# 階層インデックスを指定する場合
df = pd.read_csv(
    "testdata_multi_index.csv",
    encoding="utf-8",
    index_col=["level1", "level2"],
)

print(df, "\n")
print(df.index, "\n")
print(df.dtypes)
【実行結果】
               data     text update_datetime
level1 level2                               
1      1        100  sample1   2022/1/1 9:00
       2        200  sample2  2022/1/15 0:00
       3        300  sample3   2022/2/1 9:00
2      1        400  sample4  2022/2/15 5:00
       2        500  sample5  2022/2/28 0:00 

MultiIndex([(1, 1),
            (1, 2),
            (1, 3),
            (2, 1),
            (2, 2)],
           names=['level1', 'level2']) 

data                int64
text               object
update_datetime    object
dtype: object

上記例では、index_col=["level1", "level2"] というように複数列をリストで指定しています。これにより、階層的な MultiIndex を持った DataFrame として CSV ファイルが読み込まれていることが分かります。

pandas の Index の基本については「Indexの基本」を参考にしてください。

特定の列だけを指定して読み込む方法 usecols 引数

特定の列だけを読み込むには、read_csv 関数の usecols 引数を使用します。この引数に読み込みたい列名のリストを指定することで、CSV ファイルから必要な列のみを効率的に読み込むことができます。

import pandas as pd

# 特定の列だけを指定して読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8", usecols=["id", "text"])

print(df, "\n")
print(df.dtypes)
【実行結果】
   id     text
0   1  sample1
1   2  sample2
2   3  sample3
3   4  sample4
4   5  sample5 

id       int64
text    object
dtype: object

上記例では、usecols=["id", "text"] を指定することで、id 列と text 列のみが読み込まれていることが分かります。このように必要な列のみ指定して絞ることで、データ分析時に不要なデータを読み込む必要がなくなり処理を効率化できます。

取得するデータの型を指定する方法 dtype 引数

CSV ファイルからデータを特定の型として読み込むには、read_csv 関数の dtype 引数を使用します。この引数には、列名をキー、型を値とする辞書を指定します。

import pandas as pd

# 取得するデータの型を指定する
df = pd.read_csv(
    "testdata.csv", encoding="utf-8", dtype={"id": "float64", "data": str}
)

print(df, "\n")
print(df.dtypes)
【実行結果】
    id data     text update_datetime
0  1.0  100  sample1   2022/1/1 9:00
1  2.0  200  sample2  2022/1/15 0:00
2  3.0  300  sample3   2022/2/1 9:00
3  4.0  400  sample4  2022/2/15 5:00
4  5.0  500  sample5  2022/2/28 0:00 

id                 float64
data                object
text                object
update_datetime     object
dtype: object

上記例では、id 列を float64 として、data 列を文字列である str として読み込んでいます。型指定は Python の型名、文字列、NumPy のデータ型、型コードなどの複数の指定方法が使用できます。例えば、float"float64"numpy.float64"f8" は同じ結果となりますが、NumPy のデータ型を使用する場合は、NumPy をインポートする必要がありますので注意してください。

read_csv 関数は型を指定しない場合でも型推定を行います。ただし、開発者が期待する型で必ず読み込まれるとは限りません。例えば、数値を文字列として、またはその逆で読み込まれることもあります。予期しない型でデータが読み込まれると、分析処理で問題が発生する可能性があります。経験上、このような問題に直面することはとても多いため、dtype で各列の型を指定して読み込むことをおすすめします。

日付列を指定して取り込む方法 parse_dates 引数

CSV ファイル内の日付列を適切な日時型で読み込むには、read_csv 関数の parse_dates 引数を使用します。この引数には、日付列として扱う列名のリストを指定します。

import pandas as pd

# 日付列を指定してデータを読み込む (parse_dates引数)
df = pd.read_csv(
    "testdata.csv",
    encoding="utf-8",
    dtype={"id": int, "data": int, "text": str},
    parse_dates=["update_datetime"],
)

print(df, "\n")
print(df.dtypes)
【実行結果】
   id  data     text     update_datetime
0   1   100  sample1 2022-01-01 09:00:00
1   2   200  sample2 2022-01-15 00:00:00
2   3   300  sample3 2022-02-01 09:00:00
3   4   400  sample4 2022-02-15 05:00:00
4   5   500  sample5 2022-02-28 00:00:00 

id                          int32
data                        int32
text                       object
update_datetime    datetime64[ns]
dtype: object

上記例では、update_datetime 列を日付列として parse_dates に指定しています。この方法を使用すると、該当列は datetime64[ns] 型で読み込まれ、日時として適切に扱うことができます。複数の日付列がある場合は、列名をリストに列挙して指定します。

内部では、dateutil ライブラリを利用して日付解析が行われます。dateutil は多くの日付フォーマットに対応しているため、幅広いフォーマットの日付データを扱うことが可能です。dateutil で対応できないフォーマットの場合は、date_parser 引数にカスタム解析関数を指定することも可能です。

また、dtypes 引数と併用することが可能です。型を適切に読み込むことはデータ分析において重要です。不適切な型での読み込みは分析時に想定外の結果を引き起こすため、parse_dates 引数を利用して日付列を正確に取り込むことをおすすめします。

ヘッダー行を指定する場合 header 引数

ヘッダー行を指定して CSV ファイルを読み込む場合、read_csv 関数の header 引数を使用します。なお、ファイルの先頭行は 0 に該当します。

ヘッダー行があるファイルを読み込む場合

CSV ファイルの中には以下の testdata_header.csv のようにヘッダー行が先頭ではないデータもあります。以下の例では、3 行目がヘッダー行です。

サンプルデータ
testdata_1.txt
id,data,text,update_datetime
1,100,sample1,2022/1/1 9:00
2,200,sample2,2022/1/15 0:00
3,300,sample3,2022/2/1 9:00
4,400,sample4,2022/2/15 5:00
5,500,sample5,2022/2/28 0:00

上記例の CSV ファイルの場合は、以下のように header=2 を指定します。ファイルの 1 行目が 0 であることから、指定する数字は 2 である点に注意してください。

import pandas as pd

# ヘッダー行を指定する
df = pd.read_csv("testdata_header.csv", encoding="utf-8", header=2)

print(df, "\n")
print(df.dtypes)
【実行結果】
   id  data     text update_datetime
0   1   100  sample1   2022/1/1 9:00
1   2   200  sample2  2022/1/15 0:00
2   3   300  sample3   2022/2/1 9:00
3   4   400  sample4  2022/2/15 5:00
4   5   500  sample5  2022/2/28 0:00 

id                  int64
data                int64
text               object
update_datetime    object
dtype: object
ヘッダー行がないファイルを読み込む場合 header=None

CSV ファイルの中には、以下の testdata_header_none.csv のようにヘッダー行がないようなデータの場合があります。この場合は、header=None と指定してファイルの 1 行目からデータを読み込みます。

1,100,sample1,2022/1/1 9:00
2,200,sample2,2022/1/15 0:00
3,300,sample3,2022/2/1 9:00
4,400,sample4,2022/2/15 5:00
5,500,sample5,2022/2/28 0:00
import pandas as pd

# ヘッダー行がないcsvファイルを読み込む
df = pd.read_csv("testdata_header_none.csv", encoding="utf-8", header=None)

print(df, "\n")
print(df.dtypes)
【実行結果】
   0    1        2               3
0  1  100  sample1   2022/1/1 9:00
1  2  200  sample2  2022/1/15 0:00
2  3  300  sample3   2022/2/1 9:00
3  4  400  sample4  2022/2/15 5:00
4  5  500  sample5  2022/2/28 0:00 

0     int64
1     int64
2    object
3    object
dtype: object

header=None の場合は、列方向のインデックスには自動的に数字が割り当てられます。

上記のように header 引数をうまく使うことでヘッダーの有無に関わらず、様々な形式の CSV ファイルを柔軟に読み込むことが可能です。

CSV ファイルの書き込み to_csv

CSV ファイルへの書き込みには、pandas の DataFrame の to_csv メソッドを使用します。ここでは、DataFrame を CSVファイルに書き込む基本について説明します。

基本的な書き込み方法

DataFrame を CSV ファイルに書き込むには、to_csvメソッドを使用します。

import pandas as pd

# csvファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 別名でcsvを書き込む
df.to_csv("writedata.csv")
【出力結果の中身】
,id,data,text,update_datetime
0,1,100,sample1,2022/1/1 9:00
1,2,200,sample2,2022/1/15 0:00
2,3,300,sample3,2022/2/1 9:00
3,4,400,sample4,2022/2/15 5:00
4,5,500,sample5,2022/2/28 0:00

上記例では、testdata.csv を読み込んだ後、writedata.csv という新しいファイル名で DataFrame を書き込んでいます。to_csv メソッドを使用する際、デフォルトでは行のインデックス番号も CSV ファイルに出力されます。インデックスの出力有無を調整するには、後述する index 引数を使用します。

インデックスを出力しない index=False

DataFrame の行のインデックス番号を CSV ファイルに出力しないようにしたい場合は、index 引数を使用して index=False を指定します。この引数はインデックスが不要な場合に役立ちます。

import pandas as pd

# csvファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 別名でcsvを書き込む (インデックスは出力しない)
df.to_csv("writedata_index_false.csv", encoding="utf-8", index=False)
【出力結果の中身】
id,data,text,update_datetime
1,100,sample1,2022/1/1 9:00
2,200,sample2,2022/1/15 0:00
3,300,sample3,2022/2/1 9:00
4,400,sample4,2022/2/15 5:00
5,500,sample5,2022/2/28 0:00

この方法により、出力された CSV ファイルには DataFrame の行インデックス番号は含まれません。ヘッダーも不要な場合には、後述する header 引数と併用します。

ヘッダーを出力しない header=False

DataFrame のヘッダーを CSV ファイルに出力しないようにしたい場合は、header 引数で header=False を指定します。この引数はヘッダーが不要な場合に役立ちます。

import pandas as pd

# csvファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 別名でcsvを書き込む (インデックスは出力しない)
df.to_csv("writedata_header_false.csv", encoding="utf-8", header=False)
【出力結果の中身】
0,1,100,sample1,2022/1/1 9:00
1,2,200,sample2,2022/1/15 0:00
2,3,300,sample3,2022/2/1 9:00
3,4,400,sample4,2022/2/15 5:00
4,5,500,sample5,2022/2/28 0:00

この方法により、出力された CSV ファイルにはヘッダーが含まれません。行インデックス番号も不要な場合は、上記で紹介した index 引数と併用します。

特定の列のみ出力する columns 引数

DataFrame から特定の列のみを CSV ファイルに出力するには、to_csv メソッドの columns 引数を使用して、出力したい列名をリストで指定します。デフォルトでは、columns=None が設定されており、DataFrameの全ての列を出力します。

import pandas as pd

# CSVファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 指定した列名のみ出力する
df.to_csv("writedata_columns.csv", columns=["id", "data"])
【出力結果の中身】
,id,data
0,1,100
1,2,200
2,3,300
3,4,400
4,5,500

上記例では、id 列と data 列のみが CSV ファイルに出力されています。単一列のみを出力する場合でも、columns=["data"] のようにリスト形式で指定する必要がある点に注意してください。

また、インデックス番号やヘッダーを出力したくない場合は、上記で紹介した index 引数や header 引数と併用することができます。これらの引数を適切に組み合わせることで、出力したいデータを柔軟にカスタマイズすることが可能です。

区切り文字を指定して出力する sep 引数

DataFrame をカンマ区切り以外の形式で出力したい場合、to_csv メソッドの sep 引数を使用して区切り文字を指定することができます。デフォルトでは、CSV (Comma Separated Value) の規格に従ってカンマ「,」が区切り文字として使用されますが、sep 引数を使用することにより変更可能です。

以下の例は、タブ「\t」を区切り文字として指定し、TSV (Tab Separated Value) ファイルとして保存しています。

import pandas as pd

# CSVファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 区切り文字を指定する (\tでTSVファイルとして保存)
df.to_csv("writedata_sep.tsv", encoding="utf-8", sep="\t")
【出力結果の中身】
	id	data	text	update_datetime
0	1	100	sample1	2022/1/1 9:00
1	2	200	sample2	2022/1/15 0:00
2	3	300	sample3	2022/2/1 9:00
3	4	400	sample4	2022/2/15 5:00
4	5	500	sample5	2022/2/28 0:00

この例では、タブ「\t」を区切り文字としていますが、スペース「" "」等、他の文字を区切り文字として指定することも可能です。この柔軟性により、CSV 以外のテキストベースのデータフォーマットでデータを簡単に保存できます。

区切り文字の変更により、異なるアプリケーション間でのデータ互換性を高めることが可能になります。また、特定のデータ処理や分析ツールで要求されるフォーマットに合わせてデータをエクスポートする際にも有用です。

書き込みモードの指定 mode 引数

to_csv メソッドは、書き込みモードを指定することにより、ファイルへのデータの書き込み方を制御できます。デフォルトの書き込みモードは "w" で、これは指定したパスが存在しない場合は新規にファイルを作成し、存在する場合には上書きします。以下に、書き込みモードの指定方法について説明します。

上書きを防止したい場合 mode="x"

既存ファイルの上書きを防止したい場合は、mode="x" を指定します。これによりファイルが既に存在する場合で新規作成を試みると FileExsitsError というエラーが発生し、意図せずデータを失うことを防げます。

import pandas as pd

# CSVファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 上書き防止 ファイルが存在しない場合:新規作成、存在する場合:エラー
df.to_csv("writedata_mode_x.csv", mode="x")

ファイルが既に存在する場合には、以下のようなエラーが発生します。

FileExistsError: [Errno 17] File exists: 'writedata_mode_x.csv'
追記したい場合 mode="a"

既存ファイルにデータを追記したい場合は、mode="a" を指定します。追記モードでは、ファイルの末尾にデータが追加されます。2 回目以降の書き込みでヘッダーを省略したい場合は、header=False を指定する必要があります。

import pandas as pd

# CSVファイルを読み込む
df = pd.read_csv("testdata.csv", encoding="utf-8")

# 追記モードで追加する場合
df.to_csv("writedata_mode_a.csv")
df.to_csv("writedata_mode_a.csv", mode="a", header=False)

追記の場合は、最初の書き込みでヘッダーを含め、その後の書き込みで header=False を追加することで、ヘッダーの重複を防ぐことができます。これにより、既存ファイルに対して安全にデータを追加することが可能です。

これらの指定方法を適切に使用することで、データの上書きを防いだり、必要に応じでデータを追記したりすることができます。

まとめ

pandas の DataFrame で CSV ファイルを入出力する方法について解説しました。具体的には、read_csv 関数や to_csv メソッドの使い方を紹介しています。

Python 標準で csv モジュールが存在しますが、データ分析を行う際には、DataFrame を介してデータを取り込む方が、その後のデータ操作がより容易になります。そのため、DataFrame を用いた CSV ファイル入出力方法に慣れることは、一連のデータ分析作業を効率的に進めるうえで非常に重要です。

DataFrame を通じて CSV データを柔軟に扱えるようになることで、データの読み込み、加工、保存といった一連の作業がスムーズにできるようになりますので、しっかりと使い方を覚えてもらえたらと思います。

read_csv の公式ドキュメントはこちらを参照してください。

to_csv の公式ドキュメントはこちらを参照してください。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド
ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました