pandas

【pandas】DataFrameによるCSVファイルの入出力

【pandas】DataFrameによるcsvファイルの入出力

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

DataFrameによるCSVファイルの入出力

CSVファイルは、Comma Separated Valueの略で、カンマ「,」で区切られた値のファイルのことです。拡張子は.csvになります。各種データを保存する際のフォーマットとしてよく使用されるファイル形式でプログラミングをしているとよく使用します。

Pythonでは、CSVファイルを扱うためにcsvモジュールというものが標準で用意されており、簡単にCSVファイルの入出力が可能です。csvモジュールによる入出力は「CSVファイルの入出力」でまとめていますので興味があれば参考にしてください。

Python標準ライブラリのcsvモジュールでももちろん入出力できるのですが、データ分析でデータを使用したい場合には、pandasで用意されているread_csv関数やto_csvメソッドを使ってDataFrameとして入出力すると、その後の操作が便利です。

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

CSVファイルの読み込み read_csv

pandasのDataFrameでCSVファイルの読み込みを行う場合には、read_csv関数を使用します。以降ではいくつかの例でCSVファイルの読み込み例を紹介します。

基本的な読み込み方法

以下のCSVファイル(testdata.csv)を用いて、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関数の引数に読み込み対象のCSVのファイルパスを指定します。上記例は実行スクリプトと同フォルダにtestdata.csvがある例になっています。また、読み込む文字コードを指定したい場合は「encoding=」で指定することができます。encodingは省略しても動作します。

CSVファイルは、pandasのDataFrameとして取り込まれます。読み込んだデータの各列がどのような型で取り込まれているか確認したい場合は、dtypesプロパティで確認できます。上記例では、idとdataはint64、textとupdate_datetimeはobjectとして取り込まれています。

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

CSVファイルの中にはインデックスとなる列があることが多いかと思いますが、指定列をDataFrameのインデックスとして読み込むことができます。以下で例を使って紹介します。

なお、pandasのインデックスの基本は「Indexの基本」でまとめていますので興味があれば参考にしてください。

特定の列を指定する場合

特定の列を指定してインデックスを設定する場合には、以下のようにindex_col引数に列名を指定します。なお、「index_col=0」のように列番号で指定することもできます。

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

結果を見ると”id”列が、Int64Indexとして設定されていることが分かるかと思います。

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

データによっては以下のように階層的なインデックス情報を持っているCSVファイルもあります。この例は、level1, level2の順に階層になっているような形です。

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

このような場合には、以下のように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

複数列をリストで指定すると、上記のようにMultiIndexに設定され、アクセスに使用することができるようになります。

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

CSVファイル中に複数列がある場合には分析に必要な列のみを読み込みたくなります。

そのような場合には、usecols引数で取込対象の列を指定します。usecols引数には、以下のように取り込みたい列名をリストで指定します。

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

上記の例では、[“id”, “text”]というリストを指定することで、id列とtext列のみが読み込まれていることが分かります。

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

CSVファイルの各列を読み込む際の型を指定したい場合は、dtype引数を使用します。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

上記の例のように型を指定して読み込むことができます。指定方法としてはPythonの型や文字列、NumPyデータ型、型コード等を使用できます。

上記例のid列でいうとPython型で「float」、文字列で「”float64″」、NumPyのデータ型で「numpy.float64」、型コードで「”f8″」のいずれで指定しても結果は同じとなります。なお、NumPyのデータ型で指定する場合は、NumPyをインポートする必要があります。

また、上記例のdataの取り込みではPythonの型であるstrで指定しています。同じようにint, floatなどを指定して取り込むことができますが、どの型で取り込まれるかは環境(Python2 or 3、32 or 64ビット等)によります。DataFrameでは、文字列を想定してstrを指定するとobject型で取り込まれます。

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

CSVファイルの中には、ヘッダー行が先頭行ではないようなデータの場合があります。

例えば以下のような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

この場合は、header引数でヘッダー行を指定することができます。なお、ファイルの1行目が0に該当するため、上記ファイルだと2が3行目を意味します。

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ファイルの中には、ヘッダー行がないようなデータの場合があります。

例えば以下のようなCSVファイル(testdata_header_none.csv)の場合です。この例では先頭行からデータ行となっています。

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

この場合は、以下のように「header=None」とすることで1行目からデータとしてデータを取り込むことができます。

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

上記のようにヘッダはないものとして結果を取り込みます。列インデックスには数字が自動的に設定されることになります。

CSVファイルの書き込み to_csv

pandasのDataFrameでCSVファイルの書き込みを行う場合には、DataFrameのto_csvメソッドを使用します。

基本的な書き込み方法

DataFrameをCSVファイルに書き込みを行うには、作成したDataFrameの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

上記例では、読み込んだcsvを別名のwritedata.csvという名前でそのまま書きこんでいます。DataFrameをto_csvで出力した際にはデフォルトで行のインデックス番号も出力されることが分かるかと思います。

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

DataFrameのデータのうち、特定の列のみを出力したい場合には、以下のようにcolumns引数に対象列名をリストで指定します。デフォルトでは、columns=Noneで全ての列が出力されていることになります。

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”だけが出力されます。一列だけ出力したい場合でも、例えば「columns=[“data”]」のようにリストで指定する必要があります。

また、インデックスやヘッダーの出力が不要な場合は、以下で紹介するindex=Falseやheader=Falseと併用してください。

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

to_csvはデフォルトのままだとDataFrame自身のインデックス番号も出力します。DataFrameのインデックス番号出力が不要な場合は、以下のように「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

出力結果にはDataFrameの行インデックス番号は含まれていないことが分かるかと思います。ヘッダーも不要な場合は、以下のheader=Falseを併用してください。

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

ヘッダー行の出力が不要な場合は、以下のように「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

出力結果ではヘッダー行が出力されていないことが分かります。行のインデックス番号が不要な場合は、上記で紹介したindex=Falseを併用してください。

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

to_csvのデフォルトの区切り文字は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”」にしましたが、例えば区切りをスペース「” “」等にするといったことも可能です。

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

to_csvメソッドは書き込みモードがあり、デフォルトは”w”になっています。この場合、指定パスが存在しない場合は新規作成、存在する場合は上書きとなります。modeについていくつか指定の方法について紹介します。

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

既存ファイルを上書きしてしまうことを防止したい場合は、以下のようにmode=”x“を指定してください。

import pandas as pd

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

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

mode=”x”では、ファイルが存在しない場合は新規でファイルが作成されます。しかし、ファイルが既に存在する場合には以下のようにFileExsitsErrorというエラーとなります。

FileExistsError: [Errno 17] File exists: 'writedata_mode_x.csv'

追記したい場合 mode=”a”

既存ファイルにデータを追記していきたい場合は、以下のようにmode=”a”を指定してください。

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)

追記の場合は、ヘッダーは不要だと思いますので2回目以降の書き込みでは、上記で紹介したheader=falseを指定してもらうことになるかと思います。header=falseを指定しないと毎回ヘッダー行も含めて追記されます。

まとめ

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

Python標準でcsvモジュールがありますが、データ分析で使用する場合はDataFrameで取り込んだ方が、その後のデータ操作が容易になりますので、DataFrameでのCSVファイルの入出力について使い方に慣れてもらえればなと思います。

Note

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