pandasのDataFrameでCSVファイルを入出力する方法について解説します。
DataFrameのCSVファイル入出力
CSVファイルは、カンマで区切られたテキストファイルで各種データ保存に広く使用されています。Pythonでは、CSVファイルを扱うためのcsvモジュールというものが標準で用意されており、簡単にCSVファイルの入出力が可能です。
しかし、データ分析では、pandasで用意されているread_csv
関数やto_csv
メソッドを使って操作する方が便利です。
本記事では、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
プロパティで列のデータ型を確認できます。この例では、id
とdata
はint64
、text
とupdate_datetime
はobject
として取り込まれています。
インデックスとなる列を指定して読み込む方法 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ファイルもあります。以下は、level1
, level2
の順で階層になっているような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の基本については以下にまとめていますので参考にしてください。
特定の列だけを指定して読み込む方法 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データを柔軟に扱えるようになることで、データの読み込み、加工、保存といった一連の作業がスムーズにできるようになりますので、是非使い方を覚えてもらえたらと思います。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。