こんにちは、PowerAppsでどこまでやれるか挑戦中のあんこ先生です。
散布図やバブルチャートは要素間の関係を視覚的に表現できる優れたグラフです。
しかし、棒グラフや折れ線グラフと異なり、要素がどこに配置されるか見当がつきません。
そのため、等間隔のギャラリーでは表現することができません。
それでも、PowerAppsだけで作成したいと思いませんか?
実は、SVGとConcat関数を組み合わせれば実現できるんです!
そこで、んな方を対象に、SVGを使った散布図とバブルチャートの作り方を紹介します。
この記事を読めば、大量の要素でもかんたんにグラフ化できるようになります。
SVGを使った散布図とバブルチャートの作り方
散布図は、x軸とy軸にそれぞれ別の要素をとり、それらが交わる部分に点を打って示すグラフです。
2つの要素間に関係があるかどうかをみるのに非常に便利なグラフです。
バブルチャートは、さらにもうひとつの要素を加えて、それを円の大きさで表すグラフです。
3つのデータの関係性について、一つのグラフで見ることができます。
これらのグラフは同じ座標に複数の要素が表示される可能性があるため、ギャラリーでは表現できません。
そのため、要素の配置に制限のないSVGで表現します。
この方法なら、散布図とバブルチャートをおなじ仕組みで表現できます。
その作り方を順に解説していきます。
散布図・バブルチャートの描画領域を作成する
はじめに、グラフの描画領域を作成します。
使用するのは、たった3つのコントロールです。
SVG用の画像コントロール、y軸用縦型ギャラリー、x軸用横型ギャラリーです。
今回はコントロールを指定した記述は行わないため、名前はなんでも構いません。
ただ、移動するときに便利なので、これら3つをコンテナに格納することをオススメします。
格納用コンテナは、サイズ600*600で作成しておきます。
SVG用の画像コントロール
サイズは500*500で、座標は50,50です。
境界線は好みで設定してください。
Imageプロパティの中身は、グラフ描画時に紹介します。
y軸用縦型ギャラリー
サイズは50*600で、座標は0,0です。
軸の値表記用にラベルをひとつ格納します。
画像コントロールの左側面にぴったり付けます。
ラベルに次のコードを記述すれば、自動でメモリが表示されます。
//百分率
Sequence(6,100,-100/5)
Sequence関数で、6レコードを100から-20ずつ引いて作成します。
結果、上から100,80,60,40,20,0と表示されます。
x軸用横型ギャラリー
サイズは600*50で、座標は0,550です。
こちらも軸の値表記用にラベルをひとつ格納します。
画像コントロールの底面にぴったり付けます。
ラベルに次のコードを記述すれば、自動でメモリが表示されます。
//百分率
Sequence(6,0,20)
Sequence関数で、6レコードを0から20ずつ加えて作成します。
結果、左から0,20,40,60,80,100と表示されます。
SVGで散布図を作成する
サンプルデータの作成
次に、サンプルデータのコレクションを作成します。
散布図なので2要素与える必要があります。
今回は、理科と算数のテスト結果に関係性がないか調べるために26人分のデータを与えます。
下記コードを適当なボタンに記述してコレクションを作成してください。
100点のテストなので、両軸の上限は100のままにしています。
ClearCollect(_Scatter,
{算数:92,理科:73},{算数:56,理科:99},{算数:92,理科:91},
{算数:63,理科:86},{算数:74,理科:58},{算数:61,理科:96},
{算数:67,理科:70},{算数:63,理科:86},{算数:76,理科:65},
{算数:68,理科:52},{算数:91,理科:54},{算数:94,理科:73},
{算数:71,理科:66},{算数:79,理科:82},{算数:77,理科:63},
{算数:82,理科:85},{算数:82,理科:58},{算数:51,理科:57},
{算数:69,理科:95},{算数:78,理科:90},{算数:79,理科:74},
{算数:93,理科:62},{算数:73,理科:79},{算数:58,理科:78},
{算数:53,理科:60},{算数:89,理科:54}
)
散布図を描画する
ようやく要素(円)を表示していきます。
図のように、SVGは要素ひとつひとつにこのような記述が必要です。
cxはx座標(算数)で、左から右にいくつ移動するかを表しています。
100点のテストなので、数値分だけ右に移動します。
cyはy座標(理科)ですが、上から下にいくつ移動するかを表しています。
下から上ではないので、注意してください。
このため、描画領域の高さから理科の点数を引いた値を指定します。
rは円の半径です。
cxとcyが交わるところを中心に半径rの円を描きます。
fillは円の色です。
サンプルではRGBAで指定しています。
概要はここまでとし、試しに次のコードを画像のImageプロパティに記述してみてください。
真ん中あたりにひとつ円が描かれます。
"data:image/svg+xml,"
&EncodeUrl("
<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
<circle cx='50' cy='50' r='1' fill='RGBA(255,0,0,1)'/>
</svg>")
要素を関数で表現する
今回のサンプルは26個あるので、先ほどのコードを地道に26行分記述します。
・・・となると結構な手間ですよね。
そこで、Concat関数の出番です。
Concat関数は、テーブル内の全レコードに対してひたすら項目の中身を結合していく関数です。
項目の中身以外にも任意の文字列を追加できます。
つまり、SVGの記述部分は文字列で、要素の値はテーブル(コレクション)から持ってきて結合することができるわけです。
それでは、下記コードを画像のImageプロパティに記述してください。
"data:image/svg+xml,"
&EncodeUrl("
<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
"&Concat(_Scatter,"<circle cx='"&算数&"' cy='"&100-理科&"' r='1' fill='RGBA(255,0,0,1)' />")&"
<style>
.path{
stroke:RGBA(128, 128, 128, 1); /* 線の色 */
stroke-width: 0.2px; /* 線の太さ */
stroke-linecap: round; /* 線の形 */
stroke-dasharray: 2; /* 破線間隔 */
stroke-dashoffset: 15; /* 線の開始位置 */
}
</style>
<path class='path'
d='M0,20 L0,20 100,20 M0,40 L0,40 100,40 M0,60 L0,60 100,60 M0,80 L0,80 100,80
M20,0 L20,0 20,100 M40,0 L40,0 40,100 M60,0 L60,0 60,100 M80,0 L80,0 80,100'
fill='none'/>
</svg>")
26個の点が表示されましたか?
今回はランダムで作成したサンプルでしたが、実データなら相関が出るかもしれません。
ひと手間かければ回帰曲線も描けそうですね。
SVGでバブルチャートを作成する
サンプルデータの作成
次にバブルチャート用のサンプルデータをコレクションとして作成します。
バブルチャートは、3要素与える必要があります。
ある程度意味のあるデータでないとわかりづらいため、営業成績のサンプルを用意しました。
下記コードを適当なボタンに記述し、コレクションを作成してください。
ClearCollect(_BubbleChart,
{営業担当:"せり",訪問回数:182,客単価:6510,売上:7108950},
{営業担当:"なずな",訪問回数:207,客単価:5760,売上:6553920},
{営業担当:"ごぎょう",訪問回数:138,客単価:5830,売上:3827240},
{営業担当:"はこべら",訪問回数:60,客単価:4560,売上:1632410},
{営業担当:"ほとけのざ",訪問回数:78,客単価:7520,売上:3515410},
{営業担当:"すずな",訪問回数:186,客単価:4530,売上:5255480},
{営業担当:"すずしろ",訪問回数:44,客単価:4650,売上:2387140}
);
軸目盛の最大値を自動で算出する
軸目盛について、データソースの中身が変わるたびに調整はしていられません。
百分率なら問題ないですが、実値も確認したい場合は向きません。
そのため、x軸y軸、バブルサイズの最大値を算出して変数に格納します。
この数式はTwitterで青と緑のVBAerさんから教えていただきました。
なんかいい感じに充足率80%あたりで最大値を求めてくれます。
こちらも適当なボタンでコレクションを作成してください。
Set(_max,
{
X:RoundUp(Max(_BubbleChart,訪問回数)*2,-Len(Max(_BubbleChart,訪問回数)*2)+1)/2,
Y:RoundUp(Max(_BubbleChart,客単価)*2,-Len(Max(_BubbleChart,客単価)*2)+1)/2,
Z:RoundUp(Max(_BubbleChart,売上)*2,-Len(Max(_BubbleChart,売上)*2)+1)/2
}
)
要素を関数で表現する
サンプルは7個と少ないですが、地道に記述するのは面倒です。
散布図同様、Concat関数の出番です。
下記コードを画像のImageプロパティに記述してください。
"data:image/svg+xml,"
&EncodeUrl("
<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
"&Concat(_BubbleChart,
"<circle
cx='"&(訪問回数/_max.X)*100&"'
cy='"&(1-客単価/_max.Y)*100&"'
r='"&(売上/_max.Z)*15&"' /* 15は重み、好みで変更 */
fill='RGBA(255,0,0,0.5)' /* 透過度50%、好みで変更 */
/>"
)&"
<style>
.path{
stroke:RGBA(128, 128, 128, 1); /* 線の色 */
stroke-width: 0.2px; /* 線の太さ */
stroke-linecap: round; /* 線の形 */
stroke-dasharray: 2; /* 破線間隔 */
stroke-dashoffset: 15; /* 線の開始位置 */
}
</style>
<path class='path'
d='M0,20 L0,20 100,20 M0,40 L0,40 100,40 M0,60 L0,60 100,60 M0,80 L0,80 100,80
M20,0 L20,0 20,100 M40,0 L40,0 40,100 M60,0 L60,0 60,100 M80,0 L80,0 80,100'
fill='none'/>
</svg>")
7個の大小さまざまな円が表示されましたか?
RGBAに透過度50%を設定したので重なりもうまく表現できていると思います。
SVGを使った散布図とバブルチャートのまとめ
今回はSVGを使った散布図とバブルチャートの作り方を紹介しました。
SVGとConcat関数を組み合わせると散布図のような大量の要素を使うグラフも表現できることがわかりましたね。
すなおにPowerBIを埋め込んだ方が早い気がしないでもありませんが、きっとPowerAppsでやることに意味があると信じたいです。
またほかのグラフも対応できれば、記事にまとめたいと思います。
<style>から<path>までの記述は、ボーダーを表現しているよ。
あった方が見やすいけど、不要なら削ってください。