オライリーの本「PythonとJavaScriptではじめるデータビジュアライゼーション」に、
pythonでのcsv,jsonファイルのいい感じの入出力方法がまとまっていたのでメモ。
Jupyter Notebookで動作確認したところ、エラーが出た箇所が少しあったので、
本のコードと少し異なっているところがあります。
本の公式サイト:https://www.oreilly.co.jp/books/9784873118086/#toc
動作環境
Windows 10 Pro 64bit
Python: 3.6.1
Anaconda: 4.4.0
Jupyter Notebook: 1.0.0
使用例データ
入出力のデータは以下を使用
nobel_winners = [
{ 'category': 'Physics',
'name': 'Albert Einstein',
'nationality': 'Swiss',
'sex': 'male',
'year': 1921},
{ 'category': 'Physics',
'name': 'Paul Dirac',
'nationality': 'British',
'sex': 'male',
'year': 1933},
{ 'category': 'Chemistry',
'name': 'Marie Curie',
'nationality': 'Polish',
'sex': 'female',
'year': 1911},
]
コード例
csvファイル読み書き
pythonで辞書をcsvファイルに書き込むのは以下。
nobel_winners[0].keys()で配列の第1要素を取り出し、辞書のキーを取得している。
キーをソートするため、sorted(cols)を使い、colsに代入。
本では、cols.sort()でソートしていたが、エラーが出たため以下のように書いている。
cols = nobel_winners[0].keys()
cols = sorted(cols)
with open('data/nobel_winners.csv', 'w') as f:
f.write(','.join(cols) + '\n')
for o in nobel_winners:
row = [str(o[col]) for col in cols]
f.write(','.join(row) + '\n')
書き出したnobel_winners.csvを読み込むときは以下を実行する。
with open('data/nobel_winners.csv', 'r') as f:
for line in f.readlines():
print(line, sep='')
category,name,nationality,sex,year
Physics,Albert Enistein,Swiss,male,1921
Physics,Paul Dirac,British,male,1933
Chemistry,Marie Curie,Polish,female,1911
csvモジュールを使用しての読み書き
次にpythonのcsvモジュールを使用しての読み書きを行う。
openにnewline=''を指定しないとJupyter Notebookで実行したとき、
writer.writerowの下にさらにもう一つ改行が入ってしまったので入れている。
import csv
with open('data/nobel_winners.csv', 'w', newline='') as f:
fieldnames = nobel_winners[0].keys()
fieldnames = sorted(fieldnames)
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for w in nobel_winners:
writer.writerow(w)
csvモジュールを使用してファイルを読み込む時は以下のようになる。
import csv
with open('data/nobel_winners.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
print(row, sep='')
['category', 'name', 'nationality', 'sex', 'year']
['Physics', 'Albert Enistein', 'Swiss', 'male', '1921']
['Physics', 'Paul Dirac', 'British', 'male', '1933']
['Chemistry', 'Marie Curie', 'Polish', 'female', '1911']
行をPythonディクショナリに変換することでも、csvデータは取得できる。
そのように取得したのが以下になる。
import csv
with open('data/nobel_winners.csv') as f:
reader = csv.DictReader(f)
nobel_winners = list(reader)
for w in nobel_winners:
w['year'] = int(w['year'])
nobel_winners
[OrderedDict([('category', 'Physics'),
('name', 'Albert Enistein'),
('nationality', 'Swiss'),
('sex', 'male'),
('year', 1921)]),
OrderedDict([('category', 'Physics'),
('name', 'Paul Dirac'),
('nationality', 'British'),
('sex', 'male'),
('year', 1933)]),
OrderedDict([('category', 'Chemistry'),
('name', 'Marie Curie'),
('nationality', 'Polish'),
('sex', 'female'),
('year', 1911)])]
csvリーダーはcsvファイルから読み込むときにデータ型を推測せず、
すべてを文字列として扱うので、yearはintにキャストする必要がある。
JSONファイル読み書き
Pythonディクショナリはjsonモジュールを使ってJSONファイルに保存できます。
保存の際はjsonモジュールのdumpメソッドを用います。
import json
with open('data/nobel_winners.json', 'w') as f:
json.dump(nobel_winners, f)
JSONファイルの読み込みについては、jsonモジュールの
loadメソッドを使うことでできます。
import json
with open('data/nobel_winners.json') as f:
nobel_winners = json.load(f)
nobel_winners
[{'category': 'Physics',
'name': 'Albert Enistein',
'nationality': 'Swiss',
'sex': 'male',
'year': 1921},
{'category': 'Physics',
'name': 'Paul Dirac',
'nationality': 'British',
'sex': 'male',
'year': 1933},
{'category': 'Chemistry',
'name': 'Marie Curie',
'nationality': 'Polish',
'sex': 'female',
'year': 1911}]
jsonモジュールの読み込みでは、csvとは異なりyearの整数型は
保たれたまま読み込まれるのでキャストは不要です。
datetime型のJSONでのエンコード
datetime型を含むPythonデータをエンコードするには、
以下のようなカスタムエンコーダを作成する。
import datetime
import json
class JSONDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
else:
return json.JSONEncoder.default(self, obj)
def dumps(obj):
return json.dumps(obj, cls=JSONDateTimeEncoder)
now_str = dumps({'time': datetime.datetime.now()})
now_str
'{"time": "2017-09-03T01:03:32.634095"}'
まず、カスタマイズした日付処理エンコーダを
作成するためにJSONEncoderをサブクラス化する。
この処理では、渡された引数objがdatetimeオブジェクトであれば、
日付や日時のisoformatを返すことを実行している。
json.dumpsメソッドにcls引数にカスタム日付エンコーダを設定する。
参考文献
- PythonとJavaScriptではじめるデータビジュアライゼーション https://www.oreilly.co.jp/books/9784873118086/#toc
- CSV ファイルの読み書き https://docs.python.jp/3/library/csv.html