pythonのopenpyxlモジュールを使ってエクセル操作【6時間目:集計】

これまでは、エクセルファイルからワークブックの取り方を学び、またワークブックからはシートを取る方法を学びました。さらにはセルへのアクセスの仕方も学んだことと思います。

今回の内容は「集計」になりますが、高度な内容と感じるかもしれないです。今回はpythonの辞書が絡んできます。基本的に「退屈なことはpythonにやらせよう」と同じ内容になります。前述の本は少々理解するのに苦しむ節があります。なので、解説を増やしたいと思います。

まずはエクセルファイルをダウンロードしましょう。
automatestuff-ja/censuspopdata.xlsx at master · oreilly-japan/automatestuff-ja · GitHub

openpyxl

こちらには州と郡の人口が膨大なデータとして保存されています。行数にして70000行をこえています。

今回はこのエクセルファイルを使用した集計プログラムを解説していきます。

基本的にはこれまで学んだことの応用

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. 1~4行目 → エクセルファイルをロードしてシートをとる
  2. 5行目 → 空の辞書を作る。
  3. 9~10行目 → ここがむずかしいかもしれません。これはB,C,D列+str(row)となっていますが、forで回しているのでrowは2~sheet_max_row+1の値までどんどん増えていきます。したがって、forループを回し終わるころには膨大なデータが変数に格納されることになります。
  4. 16~20行目 → 問題はこの区間です。ここは辞書を理解しておかないとかなり厳しいです。しかもこれは多重辞書を作っている構文区間になります。

16~20行目の説明

まず5行目で count_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, 'pop0'}}}

setdefault()となっているものですから、stateとcounty変数の作られてない項目があれば前述のような形の辞書が大量に作られていくことになります。

今回はここまでにしておきたいと思います。次は多重辞書の結果をファイルに書き込む作業を解説します。

次は「pythonのopenpyxlモジュールを使ってエクセル操作【7時間目:集計の続き】」です。