pandasでcsvファイルの書き出し・追記(to_csv)
panda.DataFrame
またはpandas.Series
のデータをcsvファイルとして書き出したり既存のcsvファイルに追記したりしたい場合は、to_csv()
メソッドを使う。区切り文字を変更できるので、tsvファイル(タブ区切り)として保存することも可能。
以下の内容を説明する。
to_csv()
メソッドでcsvファイル書き出し、保存- 特定の列のみ書き出す: 引数
columns
- ヘッダー、インデックスありなし: 引数
header
,index
- エンコーディング: 引数
encoding
- 区切り文字: 引数
sep
- 書き込みモード(新規作成、上書き、追記): 引数
mode
- 浮動小数点数
float
の書式設定: 引数float_format
- 任意の書式に変換して保存
説明していない引数もあるので詳細は上記の公式ドキュメントを参照。
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)
例として以下のデータを使用する。
import pandas as pd
df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
サンプルのcsvファイルはコチラ。
以下の例はpandas.DataFrame
だが、pandas.Series
でも同様。
to_csv()メソッドでcsvファイル書き出し、保存
panda.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
Dave,68,TX,70
Ellen,24,CA,88
Frank,30,NY,57
パスは絶対パスかカレントディレクトリ(作業ディレクトリ)からの相対パスで指定する。カレントディレクトリの確認や変更については以下の記事を参照。
特定の列のみ書き出す: 引数columns
特定の列だけ書き出したい場合は、引数columns
に列名のリストを指定する。一列だけでもリストで指定する。
df.to_csv('data/dst/to_csv_out_columns.csv', columns=['age'])
name,age
Alice,24
Bob,42
Charlie,18
Dave,68
Ellen,24
Frank,30
デフォルトはNone
ですべての列が出力される。
ヘッダー、インデックスありなし: 引数header, index
ヘッダー(列名、pandas.DataFrame
のcolumns
)、インデックス(行名、pandas.DataFrame
のindex
)のありなしは引数header
, index
にTrue
or 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
68,TX,70
24,CA,88
30,NY,57
デフォルトはどちらもTrue
。
エンコーディング: 引数encoding
出力ファイルのエンコーディングは引数encoding
で指定する。
Python3の場合、デフォルトはutf-8
。
Windowsで日本語を扱う場合などはencoding='cp932'
のように、適宜設定すればOK。
区切り文字: 引数sep
区切り文字は引数sep
で指定する。
タブ文字\t
で区切ったtsvファイルとして保存したい場合は以下のように設定する。
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
Dave 68 TX 70
Ellen 24 CA 88
Frank 30 NY 57
デフォルトはカンマ','
。
書き込みモード(新規作成、上書き、追記): 引数mode
書き込みモードは引数mode
で指定する。
デフォルトは'w'
。これまでの例のように、指定したパスが存在しない場合は新規作成、存在する場合は上書きとなる。
組み込み関数open()
と同様に、既存ファイルを上書きしてしまうのを防ぎたい場合はmode='x'
とする。指定したパスが存在しない場合は新規作成、存在する場合はエラーとなる。
to_csv()
メソッドの第一引数に既存のcsvファイルのパスを指定した上でmode='a'
とすると追記となる。単純に既存ファイルの末尾にpandas.DataFrame
の内容がそのまま追記される。
一旦保存したファイルに同じデータを追記する例を示す。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
Dave,68,TX,70
Ellen,24,CA,88
Frank,30,NY,57
Alice,24,NY,64
Bob,42,CA,92
Charlie,18,CA,70
Dave,68,TX,70
Ellen,24,CA,88
Frank,30,NY,57
既存のcsvファイルからデータを読み込み、コード上の処理により行や列を追加・更新したDataFrame
を同名ファイルに書き出す場合は、mode='w'
(デフォルトなので省略可能)で上書き保存すればOK。
df.to_csv('data/dst/to_csv_out_a_new_column.csv')
df = pd.read_csv('data/dst/to_csv_out_a_new_column.csv', index_col=0)
print(df)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
df['new_col'] = 'new data'
print(df)
# age state point new_col
# name
# Alice 24 NY 64 new data
# Bob 42 CA 92 new data
# Charlie 18 CA 70 new data
# Dave 68 TX 70 new data
# Ellen 24 CA 88 new data
# Frank 30 NY 57 new data
df.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
Dave,68,TX,70,new data
Ellen,24,CA,88,new data
Frank,30,NY,57,new data
浮動小数点数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
の書式を指定できる。
表示設定の変更(上記リンク参照)では、format()
などの呼び出し可能オブジェクトで書式を指定するが、to_csv()
では%
による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' % 0.123456789)
# 1.235e-01
print('%.3e' % 123456789)
# 1.235e+08
df.to_csv('data/dst/to_csv_out_float_format_3e.csv', float_format='%.3e')
,col1,col2,col3
0,1.235e-01,1.235e+08,123456789
1,1.000e+09,0.000e+00,0
printf形式の書式については以下の公式ドキュメントを参照。
なお、上の例のように桁数を指定して保存した場合、当然ながら保存された桁数以下の情報は失われる。
任意の書式に変換して保存
引数float_format
は名前の通りデータ型が浮動小数点数float
の列に対してのみ有効。上の例のように、整数int
の列はそのまま。また、列ごとに異なる書式を指定することはできない。
整数int
の列の書式を指定したい場合や、浮動小数点数float
に対して列ごとに異なる書式を指定したい場合は、元のpandas.DataFrame
を任意の書式の文字列に変換してから保存する。
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
print(df.dtypes)
# col1 object
# col2 object
# col3 object
# dtype: object
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()
では文字列として読み込まれるので注意。数値として扱いたい場合は読み込み後に変換する必要がある。
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
数値と文字列の相互変換については以下の記事を参照。
- 関連記事: pandasで文字列と数値を相互変換、書式変更