pandasでDataFrameのcsv入出力をする

2020年12月19日

pandasを使っているとcsvファイルへのデータ入出力を高頻度で行うので忘備録としてアウトプットしておきます。

Table of Contents

基本

csvファイルに簡単にIOできます。注意点として、read_csv() はデフォルトでIndexなしとなるので、最左列が実データではなくIndexとして取り扱う場合は明示的に index_col=0 と指定する必要があります。

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], columns=['A', 'B', 'C'])

In [3]: df
Out[3]: 
   A  B  C
0  1  2  3
1  4  5  6
2  7  8  9

# csvに書き出し
In [4]: df.to_csv('test.csv')

# csvから読み込み
In [9]: read_df = pd.read_csv('test.csv', index_col=0)

In [10]: read_df
Out[10]: 
   A  B  C
0  1  2  3
1  4  5  6
2  7  8  9

Columnは指定しないとデフォルトで先頭行がColumnとみなされます。読み込むデータによってはColumnなしのデータのみの場合もあります。その場合は明示的にColumnなしheader=Noneを指定します。Columnは自動でインクリメンタル採番の整数列になります。A, B, C はデータとして読み込まれます。IndexにはデータがないのでNanとして扱われます。

In [12]: pd.read_csv('test.csv', index_col=0, header=None)
Out[12]: 
     1  2  3
0           
NaN  A  B  C
0.0  1  2  3
1.0  4  5  6
2.0  7  8  9

csvの区切り文字

エクセルとのコピペの親和性を考えるとカンマ区切りよりもタブ区切りのほうが楽なのでタブ区切りで入出力をすることも多いでしょう。区切り文字はsep引数で指定できます。実際に書き出したtsvファイルを見てみるとタブ区切りになっているはずです。

In [36]: df
Out[36]: 
   A  B  C
0  1  2  3
1  4  5  6
2  7  8  9

In [37]: df.to_csv('tab_seperated.tsv', sep='\t')

In [38]: pd.read_csv('tab_seperated.tsv', sep='\t', index_col=0)
Out[38]: 
   A  B  C
0  1  2  3
1  4  5  6
2  7  8  9

時系列データ

時系列データを読み込む際は、Indexが日付型のSeriesになるように明示的にparse_dates=Trueを与えます。IndexがDatetimeIndex型となります。ビジネスデータでは時系列データがたくさんあるので覚えておくと良いです。

In [25]: pd.read_csv('test2.csv', index_col=0, parse_dates=True)
Out[25]: 
            0  1  2
2020-01-01  1  2  3
2020-01-02  1  2  3
2020-01-03  1  2  3

# parse_dates未指定だとIndexは文字列の配列(Series)
In [27]: pd.read_csv('test2.csv', index_col=0).index
Out[27]: Index(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='object')

# IndexがDatetimeIndex型 
In [26]: pd.read_csv('test2.csv', index_col=0, parse_dates=True).index
Out[26]: DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq=None)

欠損データ

csvの欠損データはNaNとして扱われます。その影響で他のデータが整数から浮動小数付きになってしまいます。気持ちが悪いので整数として読み込みます。

In [28]: pd.DataFrame([[1,1,1], [2,2,2], [3,3]], columns=['2020-01-01', '2020-01-02', '2020-01-03']).T.to_csv('test3.csv')

# NaNが1つでもあると浮動小数
In [29]: pd.read_csv('test3.csv', index_col=0, parse_dates=True)
Out[29]: 
              0    1    2
2020-01-01  1.0  2.0  3.0
2020-01-02  1.0  2.0  3.0
2020-01-03  1.0  2.0  NaN

# 読み込んだあとに欠損データを0詰めしてint変換
In [35]: pd.read_csv('test3.csv', index_col=0, parse_dates=True).fillna(0).astype('int')
Out[35]: 
            0  1  2
2020-01-01  1  2  3
2020-01-02  1  2  3
2020-01-03  1  2  0

所感

csv入出力はかなり簡単でした。他にもエクセルファイルやRDB、Google BigQueryへの入出力もインタフェースとして備えていたので、異なるデータソースに対するETL処理も簡単に実現できそうです。


Web系エンジニアでPython好き。バックエンド/フロントエンド問わずマルチな方面でエンジニアリングしています。