[解決!Python]OpenPyXLで面グラフをExcelワークシートに作成するには:解決!Python
OpenPyXLでExcelワークシートに面グラフや3D面グラフを作成したり、グラフの種類を積み上げ面グラフ/100%積み上げ面グラフに変更したりする方法を紹介する。
面グラフ
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
values = [
('YEAR', 'A', 'B', 'C'),
(2018, 750, 500, 300),
(2019, 850, 700, 400),
(2020, 700, 650, 500),
(2021, 900, 800, 400)
]
for v in values:
ws.append(v)
from openpyxl.chart import AreaChart, Reference
rmin = ws.min_row
rmax = ws.max_row
cmin = ws.min_column
cmax = ws.max_column
chart = AreaChart()
src = Reference(ws, min_col=cmin+1, min_row=rmin, max_col=cmax, max_row=rmax)
chart.add_data(src, titles_from_data=True)
cat = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax) # 項目名の設定
chart.set_categories(cat)
chart.title = 'Sample Chart' # グラフタイトル
chart.x_axis.title = 'YEAR' # 軸ラベル
chart.y_axis.title = 'SALES'
chart.anchor = 'A7' # グラフの表示位置
chart.width = 16 # グラフのサイズ
chart.height = 8
ws.add_chart(chart)
wb.save('sample_chart.xlsx')
# グラフのスタイルの変更
chart.grouping = 'stacked' # 積み上げ面グラフ
chart.grouping = 'percentStacked' # 100%積み上げ面グラフ
3D面グラフ
from openpyxl.chart import AreaChart3D
chart = AreaChart3D()
src = Reference(ws, min_col=cmin+1, min_row=rmin, max_col=cmax, max_row=rmax)
chart.add_data(src, titles_from_data=True)
cat = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax) # 項目名の設定
chart.set_categories(cat)
chart.title = 'Sample Chart' # グラフタイトル
chart.x_axis.title = 'YEAR' # 軸ラベル
chart.y_axis.title = 'SALES'
chart.anchor = 'A24' # グラフの表示位置
chart.width = 16 # グラフのサイズ
chart.height = 8
ws.add_chart(chart)
wb.save('sample_chart.xlsx')
# 3次元面グラフでは第3軸のラベルが凡例と同じなので凡例を削除
chart.legend = None
# 系列の順序を入れ替える
chart.ser[0], chart.ser[2] = chart.ser[2], chart.ser[0]
wb.save('sample_chart.xlsx')
サンプルのワークシート
本稿では主に以下のコードで作成したワークシートを例に取る。
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
values = [
('YEAR', 'A', 'B', 'C'),
(2018, 750, 500, 300),
(2019, 850, 700, 400),
(2020, 700, 650, 500),
(2021, 900, 800, 400)
]
for v in values:
ws.append(v)
このコードを実行してできたワークシートをExcelで表示したものが以下だ。
面グラフの作成
OpenPyXLを使って面グラフを作成するには、openpyxl.chart.AreaChartクラスを使用する。その手順は以下の通り。
- Referenceクラスを使って、グラフ作成の基となる範囲を指定する
- AreaChartクラスのインスタンス(グラフ)を生成する
- グラフのタイトル、軸ラベル、項目名などの設定を行う
- グラフにデータ(上で作成したReferenceクラスのインスタンス)を渡す
- ワークシートにグラフを挿入する
面グラフ(AreaChart)で設定できる項目としては以下がある(一部)。
属性 | 説明 |
---|---|
title属性 | グラフのタイトル |
x_axis.title属性 | X軸のラベル |
y_axis.title属性 | Y軸のラベル |
anchor属性 | ワークシート上での表示位置(左上) |
width属性 | グラフの横幅 |
height属性 | グラフの高さ |
grouping属性 | グラフの種類 |
style属性 | グラフのスタイル |
set_categoriesメソッド | X軸の項目名の設定 |
AreaChartで設定できる項目(一部) |
以下にこれらの設定を行って、面グラフを作成する例を示す。
from openpyxl.chart import AreaChart, Reference
rmin = ws.min_row
rmax = ws.max_row
cmin = ws.min_column
cmax = ws.max_column
chart = AreaChart()
src = Reference(ws, min_col=cmin+1, min_row=rmin, max_col=cmax, max_row=rmax)
chart.add_data(src, titles_from_data=True)
cat = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax) # 項目名の設定
chart.set_categories(cat)
chart.title = 'Sample Chart' # グラフタイトル
chart.x_axis.title = 'YEAR' # 軸ラベル
chart.y_axis.title = 'SALES'
chart.anchor = 'A7' # グラフの表示位置
chart.width = 16 # グラフのサイズ
chart.height = 8
ws.add_chart(chart)
wb.save('sample_chart.xlsx')
title属性やanchor属性など、多くの属性については上のコードを見れば、設定方法は分かるだろう(「OpenPyXLを使ってExcelワークシートに棒グラフを作成するには」でも取り上げているのでそちらも参照されたい)。
上のコードでは、変数srcにグラフ描画の基となるセル範囲を指定している。このとき、セル範囲の一番左の列を除外している(src = Reference(ws, min_col=cmin+1, min_row=rmin, max_col=cmax, max_row=rmax))。これは一番左の列をX軸に表示する項目名(2018〜2021年)として使用するからだ。そして、変数catには今述べた一番左の列をReferenceクラスのインスタンスに指定して、それをset_categoriesメソッドに渡すようにしている。
一方、系列や凡例に使われるA/B/Cは変数srcが参照するセル範囲に含まれている。これは、add_dataメソッドでこのセル範囲をグラフ(変数chartが参照するAreaChartオブジェクト)に追加する際に「titles_from_data=True」として、セル範囲の先頭を系列名として使用するようにしているからだ。
上のコードで作成した面グラフを以下に示す。
グラフの種類を変更する
面グラフには以下のバリエーションがある。
- 面グラフ:系列の値をそれぞれY軸の値としてプロットする(デフォルト)
- 積み上げ面グラフ:各系列の値を合計したものをY軸の値とし、系列ごとに色分けしてプロットする
- 100%積み上げ面グラフ:X軸の項目ごとに各系列の値を合計したものが100%となるように、系列ごとに色分けしてプロットする
面グラフの種類を変更するにはgrouping属性の値を'standard'(面グラフ)、'stacked'(積み上げ面グラフ)、'percentStacked'(100%積み上げ面グラフ)のいずれかに設定する。
上のグラフを積み上げ面グラフに変更するコードを以下に示す。
chart.grouping = 'stacked' # 積み上げ面グラフ
これによりグラフは次のようになる。
Y軸の値が各系列の値の総計となっている(例えば、2018年ならY軸の値が「750+500+300=1550」になっている)ことに注目しよう。
100%積み上げ面グラフにするには次のようにする。
chart.grouping = 'percentStacked' # 100%積み上げ面グラフ
これによりグラフは次のようになる。
今度はY軸の最大値が100%になり、その中で各系列の値がどの程度の割合になっているかが色を分けて示されている。
3D面グラフの作成
面グラフを3Dのグラフとして描画することもできる。これにはopenpyxl.chart.AreaChart3Dクラスを使用する。
先ほど例と同じデータを使って、3D面グラフを作成するコード例を以下に示す。
from openpyxl.chart import AreaChart3D
chart = AreaChart3D()
src = Reference(ws, min_col=cmin+1, min_row=rmin, max_col=cmax, max_row=rmax)
chart.add_data(src, titles_from_data=True)
cat = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax) # 項目名の設定
chart.set_categories(cat)
chart.title = 'Sample Chart' # グラフタイトル
chart.x_axis.title = 'YEAR' # 軸ラベル
chart.y_axis.title = 'SALES'
chart.anchor = 'A24' # グラフの表示位置
chart.width = 16 # グラフのサイズ
chart.height = 8
ws.add_chart(chart)
wb.save('sample_chart.xlsx')
グラフの表示位置(anchor属性)を除けば、このコードは(2Dの)面グラフを作成するコードと同じだ。このコードを実行した結果を以下に示す。
このようにグラフが見づらくなったときには、系列の順序を入れ替えるとよい。グラフのser属性には系列ごとにデータが格納されているので、これを入れ替えるコードを以下に示す。
chart.ser[0], chart.ser[2] = chart.ser[2], chart.ser[0]
この例では、最初と最後の系列を入れ替えている。これによりグラフは次のようになる。
系列の順序を入れ替えることで、グラフが見やすくなったことが分かるはずだ。なお、3D化により増えた軸では凡例に表示されている内容が軸ラベルとしても表示されている。凡例が不要であれば、以下のように、legend属性にNoneを代入することで凡例を削除できる。
chart.legend = None
これによりグラフは次のようになる。
なお、3D面グラフでもgrouping属性を使って、積み上げ面グラフや100%積み上げ面グラフにすることが可能だ(例は省略する)
Copyright© Digital Advantage Corp. All Rights Reserved.