note.nkmk.me

pandasでcsvファイルの書き出し・追記(to_csv)

Date: 2018-04-04 / Modified: 2019-10-30 / tags: Python, pandas, CSV

panda.DataFrameまたはpandas.Seriesのデータをcsvファイルとして書き出したり既存のcsvファイルに追記したりしたい場合は、to_csv()メソッドを使う。

以下の内容を説明する。

  • to_csv()メソッドでcsvファイル書き出し、保存
  • 特定の列のみ書き出す: 引数columns
  • ヘッダー、インデックスありなし: 引数header, index
  • エンコーディング: 引数encoding
  • 区切り文字: 引数sep
  • 書き込みモード(新規作成、上書き、追記): 引数mode
  • 浮動小数点数floatの書式設定: 引数float_format
  • 任意の書式に変換して保存

説明していない引数もあるので詳細は上記の公式ドキュメントを参照。

例として以下のデータを使用する。

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でも同様。

csvファイルの読み込みについては以下の記事を参照。

そのほかpandasでのExcelファイル、jsonファイル、pickleファイルの読み書き(入出力)については以下の記事を参照。

スポンサーリンク

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.DataFramecolumns)、インデックス(行名、pandas.DataFrameindex)のありなしは引数header, indexTrue 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'。これまでの例のように、指定したパスが存在しない場合は新規作成、存在する場合は上書きとなる。

to_csv()メソッドの第一引数に既存のcsvファイルのパスを指定した上でmode='a'とすると追記となる。単純に既存ファイルの末尾にpandas.DataFrameの内容がそのまま追記される。

一旦保存したファイルに同じデータを追記する例を示す。header=Falseとしないとヘッダー(pandas.DataFramecolumns)もそのまま追記されるので注意。

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

数値と文字列の相互変換については以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事