今回も引き続き、Pythonから「PowerPoint」を操作する機能を供する「python-pptx」ライブラリを紹介していきます。
連載の目次は、以下のようになっていますので参考になさってください。
さて、ビジネスシーンにおいて数値の分布や時間推移を可視化するといったニーズは以外にも多いのではないでしょうか。
例えば、売上の月間の推移や商品の年代別の販売個数など、「マーケッティング」や「統計データ分析」を行いたいときなどです。
データの可視化には、「図」「テーブル(表)」「グラフ」などいろいろな手段はあるわけですが、これらの中でももっとも効果を発揮する要素としては、「スライドにグラフを挿入する」だと筆者は考えます。
ところで、グラフを作るとき皆さんはどのようなツールを使うでしょうか?
おそらく、PowerPoint用の資料を作るにしても一度Excelでグラフを作ってから、それをスライドに貼り付けるといった手順がほとんどだと思います。
それでも、全く間違いではないのですが、、
Excel→PowerPointという2つのツールを行き来することなくPowerPointだけで自動的にグラフが書けるとしたらより便利だと感じませんか?
そこで、連載3回目となる今回はpython-pptxだけを使ってPowerPointのグラフを作成・挿入する方法を紹介します。
この記事を読むことで次のことが分かるようなります。
それでは、次節より具体的なグラフ作成の手順について解説をしていきます。
なお、本記事内で紹介する各種クラスや関数などの使い方は一例です。省略可能なオプション引数などについては割愛していますので、詳細や不明点などは必要に応じて下記「公式ドキュメント」を参照してください。
python-pptx 公式ドキュメント(API Document)
https://openpyxl.readthedocs.io/en/stable/
1. グラフ(Chartオブジェクト)を作成する
本節では、python-pptxを使ってスライドにグラフを作成する手順を解説していきます。
python-pptxで対応できるグラフの種類は、立体(3D)を除いたほぼ全てのタイプです。それぞれタイプによって、「データ(ChartDataオブジェクト)」(後述)作成手順に違いはありますが、手順の概要はどれも同じです。
まず、はじめにグラフ作成のフローを解説します。(図1)以降の説明の➀~➄は<図1>内の番号と紐づいています。
【➀】 ➃の add_chart()メソッド でShape(グラフ)オブジェクトを生成する際に、どのタイプのグラフを作成するかあらかじめ宣言する必要があります。
このグラフタイプの定義(Enum)は、XL_CHART_TYPEクラス にまとめられているのでインポートします。
python-pptx 公式ドキュメント(XL_CHART_TYPEクラス)
XL_CHART_TYPE — python-pptx 0.6.18 documentation (python-pptx.readthedocs.io)
XL_CHART_TYPEクラスの主要な定義は以下ようなものがあります。
Exceのグラフ各種に対応しているようですが、立体(3D)グラフのサポートは対象外のようです。
【➁】 グラフを配置する場所(スライドの左上が原点)と、グラフエリアのサイズ(縦・横)を決めます。スライドの座標を決める単位は、「インチ(Inches)」「センチ(Cm)」「ポイント(Pt)」などがあります。必要な単位系のクラスをインポートします。
※特に単位を指定しなければ、Emu単位が適用されますが、我々日本人とっては扱いづらいので、上記の単位系を使うことがおすすめします。
【➂】 グラフの参照データ ChartDataオブジェクト を用意します。データクラスは作成するグラフのタイプにより個別に提供されています。詳しくは、後述しますが、棒グラフや折れ線グラフの場合は、ChartDataクラス、散布図は XyChartDataクラス を事前にインポートします。
【➃】 Shape(GraphicFrame)オブジェクトを add_chart()メソッド で取得すると同時に、Shapesコレクションに追加されます。add_chart()メソッドの引数には、➀➁➂で用意したオブジェクトを設定します。
【➄】 ➃で取得したShape(GraphicFrame)オブジェクト(グラフ・テーブル・SmartArtのコンテナ)からは、直接グラフを操作することはできません。chartプロパティ によってChartオブジェクトを取得した後、配下の属性を使ってグラフ本体の詳細設定をしていきます。
<補足事項>
また➂のデータセットの作り方について補足します。
データセットについては、Excelでのグラフ作成の知識を必要とします。
最低限、「系列とは?」「カテゴリ(系列)とは?」といったことは分かっているものとして以降の解説をします。本記事では、例えば図4の棒グラフがあった場合、データ区分の呼称は以下のように統一します。
カテゴリ(項目) とは、X軸(項目軸)の区分領域数を指します。
また系列(シリーズ)とは、それぞれのカテゴリ(項目)に対するY軸の値をグルーピングする単位のことです。
図4の例でいえば、3つのカテゴリ(項目・赤枠)があって、各カテゴリ内に3つずつ系列(青枠)を含むイメージになります。
さらに、図4(棒グラフ)は各系列で、カテゴリ(項目)を共有に取るタイプのグラフですが、散布図やバブルチャートといったグラフは、各系列ごとに独立した項目(X軸の値)を指定することができます。
以上が、グラフ作成における前提知識になります。
それでは、フロー内で登場した各オブジェクトやメソッド・属性について次項より詳しく解説していきます。
1.1 グラフの参照データ(ChartDataオブジェクト)を定義する
グラフを作成するには、その参照先となるデータをあらかじめ定義する必要があります。具体的には、先の作成フローの工程➃にある add_chart()メソッド の 引数:data に渡す ChartDataオブジェクト を用意します。
ChartDataオブジェクトの生成手順(使用するクラス)は、目的のグラフの種類によって異なるため使い分ける必要があります。まとめると以下のようになります。
大きくカテゴリ(項目)の共有の有無で区分されますが、それぞれの詳細を次項にて解説していきます。
1.1.1 折れ線・棒・円グラフの参照データの定義<CategoryChartDataクラス>
折れ線・棒グラフなど、複数の系列で共通のカテゴリを共有するタイプのグラフは、CategoryChartDataクラス もしくは ChartDataクラス のオブジェクトを参照データにとります。
書式は以下のとおりです。
上記2つのクラスは機能的には全く同じです。以下、公式ドキュメントにあるように完全なエイリアスであるとあります。今後の新規開発時には、「CategoryChartDataクラス」の使用を推奨するとコメントがあります。
ChartData is simply an alias for CategoryChartData and may be removed in a future release. All new development should use CategoryChartData for creating or replacing the data in chart types other than XY and Bubble.
<公式ドキュメントの引用> ChartDataクラスについてのコメント
オブジェクトの取得ができたところで、次は配下のプロパティ(属性)を通して「カテゴリ(項目名)」や「系列データ」を設定していきます。
つまり、カテゴリ(項目名)の設定は categoriesプロパティ (add_category()メソッド) を、系列データの設定は add_series()メソッド を「CategoryChartDataクラス」に対して行います。
書式の解説だけでは分かりずらいと思いますので、参照データを作るサンプルコードを一つ紹介します。<List1>
from pptx.chart.data import CategoryChartData # カテゴリグラフ用のデータ型を提供するクラス
# CategoryChartDataオブジェクトを作成し、カテゴリ、系列名、各データを設定
c_data = CategoryChartData() # CategoryChartDataオブジェクトを作成
c_data.categories = ['2019', '2020', '2021'] # カテゴリ名の設定
c_data.add_series('X', (1250, 2005, 1660)) # 各カテゴリのデータを指定(系列1)
c_data.add_series('Y', (620, 850, 750)) # 系列2
c_data.add_series('Z', (175, 310, 220)) # 系列3
<List1>により、3つのカテゴリ(2019, 2020, 2021)と、3つの系列(X, Y, Z)をもつデータセット(ChartDataオブジェクト)の生成ができました。
1.1.2 散布図の参照データの定義<XyChartDataクラス>
散布図など、系列ごとに個別の項目(Xの値)を指定することができるタイプのグラフは、XyChartDataクラス のオブジェクトを参照データにとります。書式は以下のとおりです
オブジェクトの取得ができたところで、今度は配下のメソッドを通して「系列の追加」と「系列のデータ(X,Yのデータ組合せ)の設定」をしていきます。
系列自体は、add_series()メソッド で得られる XySeriesDataオブジェクト によって管理されます。さらに、個々の系列データ(X,Yのデータ組合せ)は、add_data_point()メソッド により設定します。
先の<1.1.1項>ChartDataよりも、XySeriesDataを経由する分オブジェクトの階層が深く複雑になります。階層構造を以下に示します。(図7)
さて、書式の解説だけではやはり理解し辛いと思いますので、散布図の参照データを作るサンプルコードを紹介します。<List2>
from pptx.chart.data import XyChartData # XYグラフ用のデータ型を提供するクラス
# XyChartDataオブジェクトを作成し、系列とX,Yセットデータを設定する
vals1 = []
vals2 = []
for n in range(20): # データセットを作る
vals1.append((n+0.5, 0.8*(n+0.5)+1))
vals2.append((n, 0.25*n*n-0.47*n+2.75))
c_data =XyChartData() # CategoryChartDataオブジェクトを作成
s1 = c_data.add_series('系列1') # 系列名()の設定
s2 = c_data.add_series('系列2')
for val in vals1:
s1.add_data_point(val[0], val[1]) # 系列1にデータセットを設定
for val in vals2:
s2.add_data_point(val[0], val[1]) # 系列2にデータセットを設定
<List2>では、14,15行目で系列を2つ(“系列1”,”系列2”)用意します。
その系列が参照するデータは、18,21行目で設定します。データはあらかじめ、9行目、20行目で20個分のタプル(X, Y)を要素とするリストで用意しています。
1.2 グラフの本体(フレーム)を定義する(GraphicFrameオブジェクト)
<1.1項>で参照データの定義ができました、本稿ではグラフ本体をスライドに配置するためのフレーム(GraphicFrameオブジェクト)について解説します。
GraphicFrameオブジェクトはShapeオブジェクトの一種です。ですので、スライドを構成する全ての要素をまとめたShapesコレクションに追加する必要があります。そのために、次の add_chart()メソッド が用意されています。
引数:chart_type にて追加するグラフの種類を XL_CHART_TYPEクラス の定義(Enumeration)の中から選択・指定します。(図9)
また、引数:chart_data には、<1.1>項で解説した参照データ定義(ChartDataオブジェクト)を設定します。
1.3 グラフの見栄え(タイトル・軸・凡例)を整える(Chartオブジェクト)
スライドにGraphicFrame(Shape)オブジェクトを追加したので、デフォルト設定のグラフが反映されました。
ただこの時点でのデザインは、最低限のシンプルなものなので、見栄えをカスタマイズしたくなります。
GraphicFrame(Shape)オブジェクトから、chartプロパティ にて取得できる Chartオブジェクト には、グラフのカスタマイズに必要な属性が多く提供されています。本項では、使用頻度の高いグラフ設定を厳選して紹介します。
Chartオブジェクト 配下の主な関数、プロパティには以下にようなものがあります。
【 タイトル 】
グラフの「メインタイトル」を設定します。X軸、Y軸のタイトルについては後述します。
【Chartオブジェクト.プロパティ】 | 【機能】 | 【その他・詳細】 |
---|---|---|
has_title | メインタイトルの設定の有無 | True(タイトル有り)/False(タイトル無し) |
chart_title.text_frame | タイトルにテキストを設定する | 【TextFrameオブジェクト】で設定 (一般のテキスト設定と同じ) |
【 凡例 】
系列データの区別を表記する「凡例」は、グラフの必須要素となります。「凡例」に関わる属性は主として以下があります。
【Chartオブジェクト.プロパティ】 | 【機能】 | 【その他・詳細】 |
---|---|---|
has_legend | 凡例の表示の有/無の設定 | True(表示)/False(非表示) |
legend.position | 凡例の配置場所を指定する | 【XL_LEGEND_POSITIONクラス】の定義(Enum)から選択 下側(BOTTOM),右側(RIGHT),上側(UP)… |
legend.include_in_layout | 凡例のプロットエリア内配置の可否設定 | True(配置可)/False(不可) |
次の図10は「タイトル」と「凡例」に関連するプロパティの適用例です。
【 X軸/Y軸 】
軸の設定は、X軸、Y軸で個別に設定できます。X軸は category_axisプロパティ でY軸は value_axisプロパティ でAxisオブジェクトを取得して配下の属性で設定します。
設定可能な属性は殆ど共通でが、一部にY軸に特化した属性もあるので公式ドキュメントを参照してください。下記に主要な属性をまとめました。
【Chartオブジェクト.プロパティ】 | 【機能】 | 【その他・詳細】 |
---|---|---|
category_axis | X軸の書式を設定する | Axisオブジェクトで設定する |
value_axis | Y軸の書式を設定する | Axisオブジェクトで設定する |
【Axisオブジェクト.プロパティ】 | 【機能】 | 【その他・詳細】 |
---|---|---|
has_title | 軸タイトルの有効/無効の設定・読取り | True(有効)/False(無効) |
axis_title | 軸のタイトルを設定する | 【TextFrameオブジェクト】で設定する |
has_major_gridlines | 主軸線の有効/無効の設定・読取り | True(有効)/False(無効) |
minor_gridlines | 補助線の有効/無効の設定・読取り | True(有効)/False(無効) |
maximum_scale | 軸の最大値を指定する | 浮動小数で指定、Noneの場合は自動設定 |
minimum_scale | 軸の最小値を指定する | 浮動小数で指定、Noneの場合は自動設定 |
グラフの「軸(X,Y)の設定」に関連するプロパティの対応例をまとめました。(図11)
以上が、スライドへグラフを挿入する主要なオブジェクトの解説となります。
次節では、実際にグラフを挿入するコード例を2つ紹介します。
2. グラフを挿入するプログラム例<実践編>
これまでに説明してきた各種オブジェクトとメソッド・プロパティについて実例で確認します。一般的によく用いられる「棒グラフ」「散布図」を例にSampleプログラムを示します。
2.1 棒グラフのサンプルコード
次の<List3>は「棒グラフ」の作例です。
コードの概要は、カテゴリ付き参照データセット(CategoryChartDataオブジェクト)を用意した後、add_chart()メソッド でスライドにグラフを挿入します。また、凡例を追加しグラフの見栄えを整えます。
from pptx import Presentation
from pptx.chart.data import CategoryChartData # カテゴリグラフ用のデータ型を提供するクラス
from pptx.enum.chart import XL_CHART_TYPE # グラフの種類を定義するクラス
from pptx.enum.chart import XL_LEGEND_POSITION # 凡例の位置を定義するクラス
from pptx.util import Cm # cm(センチメートル)単位を定義するクラス
#--------------------------------------------------------------------------
# CategoryChartDataオブジェクトを作成し、カテゴリ、系列名、各データを設定
c_data = CategoryChartData() # CategoryChartDataオブジェクトを作成
c_data.categories = ['2019', '2020', '2021'] # カテゴリ名の設定
c_data.add_series('X', (1250, 2005, 1660)) # 各カテゴリのデータを指定(系列1)
c_data.add_series('Y', (620, 850, 750)) # 系列2
c_data.add_series('Z', (175, 310, 220)) # 系列3
#--------------------------------------------------------------------------
prs = Presentation()
sld0 = prs.slides.add_slide(prs.slide_layouts[5])
sld0.shapes[0].text = "棒グラフ(COLUMN_CLUSTERED)"
# グラフ(棒グラフ)の追加
sld0.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED # shapesコレクションにchartオブジェクト(棒グラフ)を追加
, Cm(5), Cm(6) # 引数にグラフ種類、位置、先に作ったデータを渡す
, Cm(15), Cm(10), c_data)
ch = sld0.shapes[1].chart # chartオブジェクトの取得
#--------------------------------------------------------------------------
# 凡例の設定
ch.has_legend = True # 凡例を有効にする
ch.legend.position = XL_LEGEND_POSITION.RIGHT # 凡例の配置場所を指定(上下左右)
ch.legend.include_in_layout = False # 凡例の配置場所(グラフの中外)
prs.save('Blog_棒グラフの作成.pptx')
それでは、コードのポイントを解説します。
<List3>の実行結果は以下のようになりました。
棒グラフの挿入され、凡例が表示されました。
2.2 散布図のサンプルコード
次の<List4>は「散布図」の作例です。
先の棒グラフとの大きな違いは、参照データセットの作り方にあります。系列毎にカテゴリ(項目データ)を個別指定することができるタイプのグラフですので XyChartDataクラス から参照データセットを生成することになります。また、今回は軸とマーカーの設定による見栄えも整えます。
from pptx import Presentation
from pptx.chart.data import XyChartData # XYグラフ用のデータ型を提供するクラス
from pptx.enum.chart import XL_CHART_TYPE # グラフの種類を定義するクラス
from pptx.enum.chart import XL_MARKER_STYLE # グラフのマーカーの種類を定義するクラス
from pptx.util import Cm
#--------------------------------------------------------------------------
# XyChartDataオブジェクトを作成し、系列とX,Yセットデータを設定する
vals1 = []
vals2 = []
for n in range(20): # データセットを作る
vals1.append((n+0.7, 0.6*(n+0.7)+1.5))
vals2.append((n, 0.35*n*n-0.27*n+3.75))
c_data =XyChartData() # CategoryChartDataオブジェクトを作成
s1 = c_data.add_series('系列1') # 系列名()の設定
s2 = c_data.add_series('系列2')
for val in vals1:
s1.add_data_point(val[0], val[1]) # 系列1にデータセットを設定
for val in vals2:
s2.add_data_point(val[0], val[1]) # 系列2にデータセットを設定
#--------------------------------------------------------------------------
prs = Presentation()
sld0 = prs.slides.add_slide(prs.slide_layouts[6])
# グラフ(散布図)の追加
# shapesコレクションにchartオブジェクト(棒グラフ)を追加
# 引数にグラフ種類、位置、先に作ったデータを渡す
ch = sld0.shapes.add_chart(XL_CHART_TYPE.XY_SCATTER,
Cm(5), Cm(6), Cm(18), Cm(13), c_data).chart
#--------------------------------------------------------------------------
# [軸の設定]
axis = ch.value_axis # value_axisオブジェクト(値軸)の取得
axis.has_title = True # 軸のタイトルを有効
axis.axis_title.text_frame.text = "Y" # 軸のタイトル名の設定
#--------------------------------------------------------------------------
# [マーカーの設定]
sers = ch.series # 系列を取得
sers[0].marker.style = XL_MARKER_STYLE.CIRCLE # 系列1のマーカースタイルを設定(〇)
sers[0].marker.size = 8 # 系列1のマーカーサイズを設定
sers[1].marker.style = XL_MARKER_STYLE.TRIANGLE # 系列2のマーカースタイルを設定(△)
sers[1].marker.size = 8 # 系列2のマーカーサイズを設定
prs.save('Blog_散布図の作成.pptx')
それでは、コードのポイントを解説します。
<List4>の実行結果は以下のようになりました。
散布図(2系列、20ポイント)が追加され、Y軸のタイトルとプロットにマーカー(●,▲)が表示されました。
3. まとめ
いかがでしたでしょうか?
今回は「python-pptxライブラリ」を使って、グラフ作成する手順について解説してきました。
分かりやすい資料をつくるコツの一つは、無機質な数値データから「どのようなことが言えるのか?」「今後の期待値と予測はどうなるか?」といったことを「グラフ」で客観的に示すことです。
今回紹介したテクニックを活用することで、PythonだけでPowerPoint用のグラフを作成することができるのです。
最後にここまでの記事内容をまとめておきましょう。
➀. Python-pptxではグラフをShapeオブジェクトとして管理している。Shapeオブジェクトは、add_chart()メソッド でスライドに追加できる。
➁.グラフの参照データはChartDataオブジェクトで定義するが、グラフの形態(系列ごとのX軸の共有方法の違い)によって必要なクラスを使い分ける。
(CategoryChartDataクラス と XyChartDataクラス がなど)
➂. グラフの構成要素やデザインのカスタマイズは、さらに Chartオブジェクト を取得した上で、その配下の属性にて対応する。
さて、次回はスライドにテーブル(表)を挿入する方法について解説をします。
テーブルもまた、データの整理や分かりやすい資料づくりの大事な要素となります。
次回もポイントを絞り図解で解説しますので、参考にして頂けたら幸いです。リンク先はこちらになります。↓
最後までお読み頂きありがとうございました。