pandasでCSVファイルの書き込み・追記(to_csv)
pandas.DataFrame
, Series
をCSVファイルとして書き込み(出力)するにはto_csv()
メソッドを使う。既存のCSVファイルへの追記も可能。区切り文字を変更できるので、TSVファイル(タブ区切り)として保存することもできる。
- pandas.DataFrame.to_csv — pandas 2.0.3 documentation
- pandas.Series.to_csv — pandas 2.0.3 documentation
本記事で扱っていない引数もあるので詳細は上記の公式ドキュメントを参照。
CSVファイルの読み込み(入力)については以下の記事を参照。
pandasでのExcel, JSON, pickleファイルの読み書き(入出力)については以下の記事を参照。
- 関連記事: pandasでExcelファイル(xlsx, xls)の読み込み(read_excel)
- 関連記事: pandasでExcelファイル(xlsx, xls)の書き込み(to_excel)
- 関連記事: pandasでJSON文字列・ファイルを読み込み(read_json)
- 関連記事: pandas.DataFrameをJSON文字列・ファイルに変換・保存(to_json)
- 関連記事: pandas.DataFrame, Seriesをpickleで保存、読み込み(to_pickle, read_pickle)
本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。以下のpandas.DataFrame
を例として使う。
import pandas as pd
print(pd.__version__)
# 2.0.3
df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0).head(3)
print(df)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
以下の例はpandas.DataFrame
だが、pandas.Series
でも同様。
to_csv()でCSVファイルに書き込み・保存(出力)
pandas.DataFrame
およびpandas.Series
のメソッドとしてto_csv()
が用意されている。
第一引数にパスを指定すると、CSVファイルとして出力される。
df.to_csv('data/dst/to_csv_out.csv')
name,age,state,point
Alice,24,NY,64
Bob,42,CA,92
Charlie,18,CA,70
パスは絶対パスかカレントディレクトリ(作業ディレクトリ)からの相対パスで指定する。カレントディレクトリの確認や変更については以下の記事を参照。
特定の列のみ出力: 引数columns
特定の列だけ出力したい場合は、引数columns
に列名のリストを指定する。一列だけでもリストで指定する。
df.to_csv('data/dst/to_csv_out_columns.csv', columns=['age', 'point'])
name,age,point
Alice,24,64
Bob,42,92
Charlie,18,70
デフォルトはNone
で、すべての列が出力される。
ヘッダー、インデックス出力の有無: 引数header, index
ヘッダー(列名、pandas.DataFrame
のcolumns
)、インデックス(行名、pandas.DataFrame
のindex
)の出力の有無は、引数header
, index
にTrue
かFalse
で指定する。
df.to_csv('data/dst/to_csv_out_header_index.csv', header=False, index=False)
24,NY,64
42,CA,92
18,CA,70
デフォルトはどちらもTrue
で、これまでの例のように、ヘッダーもインデックスも含めて出力される。
エンコーディング: 引数encoding
出力ファイルのエンコーディングは引数encoding
で指定する。デフォルトはutf-8
。
必要に応じてencoding='shift_jis'
やencoding='cp932'
のように適宜設定する。
区切り文字: 引数sep
区切り文字を引数sep
で指定できる。デフォルトはカンマ','
でCSVファイルとして出力される。
タブ文字\t
で区切ったTSVファイルとして保存したい場合はsep='\t'
とすればよい。
df.to_csv('data/dst/to_csv_out.tsv', sep='\t')
name age state point
Alice 24 NY 64
Bob 42 CA 92
Charlie 18 CA 70
書き込みモード(新規作成・上書き・追記): 引数mode
引数mode
に書き込みモードを指定できる。組み込み関数open()
と同じ値を指定可能。
デフォルトはmode='w'
。指定したパスが存在しない場合は新規作成、存在する場合は上書きとなる。
既存ファイルに上書きしてしまうのを防ぎたい場合はmode='x'
とする。指定したパスが存在しない場合は新規作成、存在する場合はエラーとなり上書きされない。
# df.to_csv('data/dst/to_csv_out.csv', mode='x')
# FileExistsError: [Errno 17] File exists: 'data/dst/to_csv_out.csv'
追記はmode='a'
。既存ファイルの末尾に新たな行として追記される。
一度保存したファイルに同じデータを追記する例を示す。header=False
としないとヘッダー(pandas.DataFrame
のcolumns
)もそのまま追記されるので注意。
df.to_csv('data/dst/to_csv_out_a.csv')
df.to_csv('data/dst/to_csv_out_a.csv', mode='a', header=False)
name,age,state,point
Alice,24,NY,64
Bob,42,CA,92
Charlie,18,CA,70
Alice,24,NY,64
Bob,42,CA,92
Charlie,18,CA,70
mode='a'
による追記は行の追加。列を追加したい場合は、対象のファイルを読み込み、列を追加し、mode='w'
(デフォルトなので省略可能)で同名ファイルに上書き保存する。要素の値を更新する場合も同様。
df.to_csv('data/dst/to_csv_out_a_new_column.csv')
df_new = pd.read_csv('data/dst/to_csv_out_a_new_column.csv', index_col=0)
print(df_new)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
df_new['new_col'] = 'new data'
print(df_new)
# age state point new_col
# name
# Alice 24 NY 64 new data
# Bob 42 CA 92 new data
# Charlie 18 CA 70 new data
df_new.to_csv('data/dst/to_csv_out_a_new_column.csv')
name,age,state,point,new_col
Alice,24,NY,64,new data
Bob,42,CA,92,new data
Charlie,18,CA,70,new data
欠損値NaNの扱い: 引数na_rep
欠損値NaN
を含むpandas.DataFrame
を例とする。
df_nan = df.copy()
df_nan.iat[0, 1] = float('nan')
df_nan.iat[1, 2] = float('nan')
print(df_nan)
# age state point
# name
# Alice 24 NaN 64.0
# Bob 42 CA NaN
# Charlie 18 CA 70.0
デフォルトでは欠損値は空白(空文字)として出力される。
df_nan.to_csv('data/dst/to_csv_out_nan.csv')
name,age,state,point
Alice,24,,64.0
Bob,42,CA,
Charlie,18,CA,70.0
引数na_rep
に欠損値を置き換える文字列を指定できる。
df_nan.to_csv('data/dst/to_csv_out_nan_rep.csv', na_rep='NaN')
name,age,state,point
Alice,24,NaN,64.0
Bob,42,CA,NaN
Charlie,18,CA,70.0
pandas.DataFrame
の欠損値の処理については以下の記事を参照。
浮動小数点数floatの書式設定: 引数float_format
以下のpandas.DataFrame
を例とする。
df = pd.DataFrame({'col1': [0.123456789, 1000000000.0],
'col2': [123456789.0, 0.0],
'col3': [123456789, 0]})
print(df)
# col1 col2 col3
# 0 1.234568e-01 123456789.0 123456789
# 1 1.000000e+09 0.0 0
print(df.dtypes)
# col1 float64
# col2 float64
# col3 int64
# dtype: object
print()
での表示は指数表記となっているが、これはあくまでも表示設定によるもので、値自体が丸められているわけではない。
print(df.iat[0, 0])
# 0.123456789
print(df.iat[1, 0])
# 1000000000.0
to_csv()
で保存する場合、デフォルトでは値がそのまま保存される。
df.to_csv('data/dst/to_csv_out_float_default.csv')
,col1,col2,col3
0,0.123456789,123456789.0,123456789
1,1000000000.0,0.0,0
to_csv()
の引数float_format
で、保存時の浮動小数点数float
の書式を指定できる。%
によるprintf形式で用いる書式化文字列、または、format()
などの呼び出し可能オブジェクトを指定する。
printf形式で指定する例。小数点以下の桁数を3桁にしている。
print('%.3f' % 0.123456789)
# 0.123
print('%.3f' % 123456789)
# 123456789.000
df.to_csv('data/dst/to_csv_out_float_format_3f.csv', float_format='%.3f')
,col1,col2,col3
0,0.123,123456789.000,123456789
1,1000000000.000,0.000,0
呼び出し可能オブジェクトで指定する例。小数点以下3桁の指数表記にしている。
print('{:.3e}'.format(0.123456789))
# 1.235e-01
print('{:.3e}'.format(123456789))
# 1.235e+08
df.to_csv('data/dst/to_csv_out_float_format_3e.csv', float_format='{:.3e}'.format)
,col1,col2,col3
0,1.235e-01,1.235e+08,123456789
1,1.000e+09,0.000e+00,0
なお、桁数を指定して保存した場合、当然ながら保存された桁数以下の情報は失われる。
任意の書式に変換して保存
引数float_format
は名前の通りデータ型が浮動小数点数float
の列に対してのみ有効。整数int
の列はそのまま。また、列ごとに異なる書式を指定することはできない。
整数int
の列の書式を指定したい場合や、浮動小数点数float
に対して列ごとに異なる書式を指定したい場合は、元のpandas.DataFrame
を任意の書式の文字列に変換してから保存する。
df = pd.DataFrame({'col1': [0.123456789, 1000000000.0],
'col2': [123456789.0, 0.0],
'col3': [123456789, 0]})
df['col1'] = df['col1'].map('{:.3f}'.format)
df['col2'] = df['col2'].map('{:.3e}'.format)
df['col3'] = df['col3'].map('{:#010x}'.format)
print(df)
# col1 col2 col3
# 0 0.123 1.235e+08 0x075bcd15
# 1 1000000000.000 0.000e+00 0x00000000
df.to_csv('data/dst/to_csv_out_float_format_str.csv')
,col1,col2,col3
0,0.123,1.235e+08,0x075bcd15
1,1000000000.000,0.000e+00,0x00000000
この例のように、整数int
を16進数で保存した場合、pd.read_csv()
では文字列として読み込まれるので注意。数値として扱いたい場合は読み込み後に変換する必要がある。
- 関連記事: pandasで文字列と数値を相互変換、書式変更
df = pd.read_csv('data/dst/to_csv_out_float_format_str.csv', index_col=0)
print(df)
# col1 col2 col3
# 0 1.230000e-01 123500000.0 0x075bcd15
# 1 1.000000e+09 0.0 0x00000000
print(df.dtypes)
# col1 float64
# col2 float64
# col3 object
# dtype: object
df['col3'] = df['col3'].map(lambda x: int(x, 16))
print(df)
# col1 col2 col3
# 0 1.230000e-01 123500000.0 123456789
# 1 1.000000e+09 0.0 0
print(df.dtypes)
# col1 float64
# col2 float64
# col3 int64
# dtype: object