これまでは、エクセルファイルからワークブックの取り方を学び、またワークブックからはシートを取る方法を学びました。さらにはセルへのアクセスの仕方も学んだことと思います。
今回の内容は「集計」になりますが、高度な内容と感じるかもしれないです。今回はpythonの辞書が絡んできます。基本的に「退屈なことはpythonにやらせよう」と同じ内容になります。前述の本は少々理解するのに苦しむ節があります。なので、解説を増やしたいと思います。
まずはエクセルファイルをダウンロードしましょう。
automatestuff-ja/censuspopdata.xlsx at master · oreilly-japan/automatestuff-ja · GitHub
こちらには州と郡の人口が膨大なデータとして保存されています。行数にして70000行をこえています。
今回はこのエクセルファイルを使用した集計プログラムを解説していきます。
Pythonとopenpyxlを活用したデータ集計の例
サンプルコード
このコードはExcelファイル(censuspopdata.xlsx)から人口データを読み取り、州ごとの郡データを集計して、Pythonの辞書としてファイルに出力する処理を行っています。
import openpyxl, pprint, os print('ワークブックを開いています。') wb = openpyxl.load_workbook('censuspopdata.xlsx') sheet = wb.get_sheet_by_name('Population by Census Tract') county_data = {} # county_dataに人口と地域数を格納する print('行を読み込んでいます') for row in range(2, sheet.max_row + 1): state = sheet['B' + str(row)].value county = sheet['C' + str(row)].value pop = sheet['D' + str(row)].value # 新しいテキストファイルを開き、county_dataの内容を書き込む # 州のキーが確実に存在するようにする。 county_data.setdefault(state, {}) # 州の郡のキーが確実に存在するようにする county_data[state].setdefault(county, {'tracts': 0, 'pop':0}) county_data[state][county]['tracts'] += 1 county_data[state][county]['pop'] += int(pop) # 新しいテキストファイルを開き、county_dataの内容を書き込む print('結果を書き込み中...') result_file = open('census2010.py', 'w') result_file.write('all_data = ' + pprint.pformat(county_data)) result_file.close() print('完了')
なにをしているのかぱっとみてわからないと思います。
- 1~4行目 → エクセルファイルをロードしてシートを取得しています。
- 5行目 → 空の辞書を作成しています。
- 9~10行目 → ここが難しいかもしれません。これはB、C、D列に対応するセルの値を文字列として取得していますが、forループを使っているため、rowは2からsheet_max_row + 1の値まで増加していきます。したがって、forループを回し終わる頃には膨大なデータが変数に格納されることになります。
- 16~20行目 → 問題はこの範囲です。ここでは辞書の概念を理解していないと理解が難しいです。さらに、この範囲では多重辞書が作成されています。
16~20行目の説明
まず、5行目でcounty_data = {}
という空の辞書を作成しています。16行目のsetdefault(キー, 値)
という関数の機能は、キーが未定義の場合のみ、値を追加するというものです。
18行目はcounty_data[state]
となりますが、これは理解しにくいかもしれません。これは、辞書名[キー名]とすることで、値にアクセスすることになります。さらにsetdefault()
を使っているので、state
の値にさらに辞書を作成して多重辞書にしています。
例をみてみましょう。
hoge = {'foo': 10, 'fuga': 20} hoge['foo'] # 出力:10(値にアクセスできていることがわかりますでしょうか?)
19~20行目はさらに理解が難しいかもしれません。これは最終的にはstate
とcounty
に対応するtracts
の値に1を加え、pop
の値にはpop
の値をそのまま足しています。ここは非常に難しいかもしれません。まず[][][]
となぜ3つも並んでいるのかわからないかもしれません。
例をみてみましょう。以下のような多重辞書があったとしていきなりfoo[okane]としてもエラーになってしまいます。
foo = {'saifu': {'okane': 1000}} foo[okane] # エラーになってしまう # 多重辞書の深い値にアクセスするにはキーを順に辿る必要があります。
結局のところ次のような形の辞書ができます。
# county_data = {state: {county: {'tracts': 0, 'pop': 0}}}
setdefault()
となっているものですから、state
とcounty
変数が作られていない項目があれば前述のような形の辞書が大量に作成されていくことになります。
今回はここまでにしておきたいと思います。次は多重辞書の結果をファイルに書き込む作業を解説します。
コメント