はじめに¶
pythonでcsvを取り扱うには,pandas
を利用するのが一番便利.お決まりのimport pandas as pd
でimportし,pa.read_csv(file_path)
関数で簡単に読み取ることができる.
しかしながら,DataFrame
のカラム名のデータタイプについて少し注意が必要なので,その点についてまとめる.
具体的には,csv_read()
で読み取ると,カラムのデータタイプはstring
型で読み取られてしまう.通し番号などで,カラム名もint
型で扱いたい場合に少し不便.
発生する問題¶
pd.read_csv(file_path)
関数の,必須引数はファイルパスである.これは絶対パスでも相対パスでもOK.
今回は,以下のような構造のcsvファイル(test.csv)を用意する.
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.0 | 0.1 | 0.2 | 0.3 |
1 | 1.0 | 1.1 | 1.2 | 1.3 |
2 | 2.0 | 2.1 | 2.2 | 2.3 |
3 | 3.0 | 3.1 | 3.2 | 3.3 |
4 | 4.0 | 4.1 | 4.2 | 4.3 |
5 | 5.0 | 5.1 | 5.2 | 5.3 |
このファイルのindexは[0,1,2,3,4,5]
で,columnは[0,1,2,3]
で,両方ともint
型で扱いたいとする.各要素はfloat
型のなんらかのデータである.(例としてわかりやすいように規則的に値を定めた)
import pandas as pd
#テスト用にtable1を作成し,csv出力
original_table = pd.DataFrame(index=range(6),columns=range(4))
for i in range(6):
for c in range(4):
original_table.loc[i,c] = i+0.1*c
original_table
のindex,columnのデータタイプを確認する.
print("index:",original_table.index.dtype)
print("column:",original_table.columns.dtype)
int
型となっている.
次に,このoriginal_table
を一時,csvに書き出し,再度読み込む.
original_table.to_csv("test.csv", encoding="utf-8-sig")
copy_table = pd.read_csv("test.csv", encoding="utf-8-sig", index_col=0)
余談だが,csvは必ずBOM付きで扱うようにしている.これは,某社の表計算ソフトでもストレスなく開けるようにするためである.
BOMの扱いについては諸説あると思うが,理解のない人にデータを渡したときに「エクセルで見れない=文字化け=お前が悪い」って言われないための防衛線である.
話を戻して,copy_table
のindex,columnのデータタイプを確認する.
print("index:",copy_table.index.dtype)
print("column:",copy_table.columns.dtype)
int
型だが,columnはobject
となってしまっている.そのため,以下のようにtable
から値を読み取れない.
#確認のため,original_tableから
#int型で要素指定
print(original_table.loc[4,1])
#次にcopy_tableから
#int型で要素指定
print(copy_table.loc[4,1])
#str型で要素指定
print(copy_table.loc[4,"1"])
str
型にすればOKなのだが,いらぬバグを生みそうな気がするだろう.
おそらく,カラム名として想定されているのが,id, name, stateなどの文字列を想定しているため,pd.read_csv()
がこのような挙動をするのだろう.
解決策¶
csv読み取り時点で,カラムデータタイプの指定オプションはなさそう.(もしかしたあるのかも)
とりあえずの策としては,以下のように読み取り直後にrename()
を利用してカラムを書き換えてしまう方法がある.
copy_table = pd.read_csv("test.csv", encoding="utf-8-sig", index_col=0)
copy_table = copy_table.rename(columns={c:int(c) for c in copy_table.columns})
#int型で要素指定
print(copy_table.loc[4,1])
rename
関数の引数として,{変更前:変更後}
のように,key
を変更前,value
を変更後の値とした辞書型を渡す.
おわりに¶
カラムをint
型で扱う機会は少ないかもれないが,今回の内容はpd.read_csv()
のデフォルトの挙動として頭に入れといた方が良いだろう.
読み取り時点で指定できる方法があれば知りたい.