【コピペでGoogleCharts】レーダーチャートの使い方

GoogleChartsを使って、WordPressブログにレーダーチャートを埋めこむための方法を解説します。

レーダーチャートを使うことで、複数の評価項目を直感的に読みとることができます。

なぜなら、レーダーチャートはデータの大小やバランスを視覚的に表示できるからです。

コードをコピペするだけですぐに使えますので、ブログの用途に合わせてご利用ください。

「どうやってブログに貼り付ければいいかわからない。」
という方は、先にWordPressブログでGoogleChartsを使うための基本をご覧ください。

変更履歴
  • レーダーチャートを同一記事内で複数箇所に表示できるようにコードを修正しました。
  • 一部のテーマで、レーダーチャート内のフォントサイズが変更できない不具合を修正しました。

コピペで使えるレーダーチャート

レーダーチャートは、クモの巣っぽい見た目のグラフです。

複数の項目のデータを表示し、量の大小を把握しつつ、そのバランスや特徴を見るときなどに使用されます。

一般的には、外にいくほど(レーダーが大きいほど)良いと評価します。

基本のレーダーチャート

ブログでレーダーチャートの用途として想定されるのが、商品やサービスの定量的な評価です。

例えば、価格.comなどでおなじみの満足度をレーダーチャートにしてみます。

【例】iPhone ナンバリングモデルの満足度

【例】iPhone SEモデルの満足度

このグラフのポイント
  • Google Chartsを使ったレーダーチャートの基本デザイン
  • チャートデータの中で、チャートを表示するブロックIDを指定することで、同一記事内でチャートを複数箇所に表示できる。
  • 6項目を5点満点で数値化している。
HTML
<div style="width: 100%; text-align: center;">
  <div id="radar_1"></div>
</div>
HTML
<div style="width: 100%; text-align: center;">
  <div id="radar_2"></div>
</div>
HTML
<!-- 基本のレーダーチャート -->
<script type="text/javascript">

google.charts.load('upcoming', {
  'packages': ['vegachart']
}).then(loadCharts);

function loadCharts() {
  // レーダーチャートのデータ
  const chartData = [
    ["radar_1","iPhone 12 の満足度", "#B82E2E", [
      ["デザイン", 4.54],
      ["携帯性", 4.31],
      ["レスポンス", 4.80],
      ["画面表示", 4.69],
      ["バッテリー", 4.23],
      ["カメラ", 4.53]
    ]],
    ["radar_1","iPhone 13 の満足度", "#B82E2E", [
      ["デザイン", 4.43],
      ["携帯性", 3.96],
      ["レスポンス", 4.54],
      ["画面表示", 4.49],
      ["バッテリー", 4.37],
      ["カメラ", 4.27]
    ]],
    ["radar_2","iPhone SE(第2世代) の満足度", "#6633CC", [
      ["デザイン", 4.24],
      ["携帯性", 4.67],
      ["レスポンス", 4.64],
      ["画面表示", 4.17],
      ["バッテリー", 3.49],
      ["カメラ", 3.98]
    ]],
    ["radar_2","iPhone SE(第3世代) の満足度", "#6633CC", [
      ["デザイン", 3.71],
      ["携帯性", 4.39],
      ["レスポンス", 4.79],
      ["画面表示", 3.51],
      ["バッテリー", 3.28],
      ["カメラ", 3.45]
    ]],
  ];

  for (var i = 0; i < chartData.length; i++) {
    for (var j = 0; j < chartData[i][3].length; j++) {
      chartData[i][3][j][2] = chartData[i][1];
    }
    addChart(chartData[i][1], chartData[i][3], chartData[i][2], chartData[i][0]);
  }
}

function addChart(title, data, color, chartId) {
  // 値スケール
  const valueScale = [0, 5];
  // 値フォーマット
  const valueFormat = '1';
  // レーダーの枠線の太さ
  const valueStrokeWidth = 1.5;
  // レーダーの領域の不透明度
  const valueOpacity = 0.1;
  // レーダーの値のフォントサイズ
  const valueValtext = 14;
  // レーダーのラベルのフォントサイズ
  const valueLabeltext = 12;

  const dataTable = new google.visualization.DataTable();
  dataTable.addColumn({
    type: 'string',
    'id': 'key'
  });
  dataTable.addColumn({
    type: 'number',
    'id': 'value'
  });
  dataTable.addColumn({
    type: 'string',
    'id': 'category'
  });
  dataTable.addRows(data);

  const options = {
    'vega': {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "width": 250,
      "height": 300,
      "autosize": "none",
      "title": {
        "text": title,
        "anchor": "middle",
        "fontSize": 16,
        "dy": -8,
        "dx": {
          "signal": "-width/4"
        },
        "subtitle": ""
      },
      "signals": [{
        "name": "radius",
        "update": "90"
      }],
      "data": [{
          "name": "table",
          "source": "datatable",
        },
        {
          "name": "keys",
          "source": "table",
          "transform": [{
            "type": "aggregate",
            "groupby": ["key"]
          }]
        }
      ],
      "scales": [{
          "name": "angular",
          "type": "point",
          "range": {
            "signal": "[-PI, PI]"
          },
          "padding": 0.5,
          "domain": {
            "data": "table",
            "field": "key"
          }
        },
        {
          "name": "radial",
          "type": "linear",
          "range": {
            "signal": "[0, radius]"
          },
          "zero": true,
          "nice": false,
          "domain": valueScale,
        }
      ],
      "encode": {
        "enter": {
          "x": {
            "signal": "width/2"
          },
          "y": {
            "signal": "height/2 + 20"
          }
        }
      },
      "marks": [{
          "type": "group",
          "name": "categories",
          "zindex": 1,
          "from": {
            "facet": {
              "data": "table",
              "name": "facet",
              "groupby": ["category"]
            }
          },
          "marks": [{
              "type": "line",
              "name": "category-line",
              "from": {
                "data": "facet"
              },
              "encode": {
                "enter": {
                  "interpolate": {
                    "value": "linear-closed"
                  },
                  "x": {
                    "signal": "scale('radial', datum.value) * cos(scale('angular', datum.key))"
                  },
                  "y": {
                    "signal": "scale('radial', datum.value) * sin(scale('angular', datum.key))"
                  },
                  "stroke": {
                    "value": color
                  },
                  "strokeWidth": {
                    "value": valueStrokeWidth
                  },
                  "fill": {
                    "value": color
                  },
                  "fillOpacity": {
                    "value": valueOpacity
                  }
                }
              }
            },
            {
              "type": "text",
              "name": "value-text",
              "from": {
                "data": "category-line"
              },
              "encode": {
                "enter": {
                  "x": {
                    "signal": "datum.x + 14 * cos(scale('angular', datum.datum.key))"
                  },
                  "y": {
                    "signal": "datum.y + 14 * sin(scale('angular', datum.datum.key))"
                  },
                  "text": {
                    "signal": "format(datum.datum.value,'" + valueFormat + "')"
                  },
                  "opacity": {
                    "signal": "datum.datum.value > 0.01 ? 1 : 0"
                  },
                  "align": {
                    "value": "center"
                  },
                  "baseline": {
                    "value": "middle"
                  },
                  "fontWeight": {
                    "value": "bold"
                  },
                  "fill": {
                    "value": color
                  },
                  "fontSize": {
                    "value": valueValtext
                  }
                }
              }
            }
          ]
        },
        {
          "type": "rule",
          "name": "radial-grid",
          "from": {
            "data": "keys"
          },
          "zindex": 0,
          "encode": {
            "enter": {
              "x": {
                "value": 0
              },
              "y": {
                "value": 0
              },
              "x2": {
                "signal": "radius * cos(scale('angular', datum.key))"
              },
              "y2": {
                "signal": "radius * sin(scale('angular', datum.key))"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        },
        {
          "type": "text",
          "name": "key-label",
          "from": {
            "data": "keys"
          },
          "zindex": 1,
          "encode": {
            "enter": {
              "x": {
                "signal": "(radius + 11) * cos(scale('angular', datum.key))"
              },
              "y": [{
                  "test": "sin(scale('angular', datum.key)) > 0",
                  "signal": "5 + (radius + 11) * sin(scale('angular', datum.key))"
                },
                {
                  "test": "sin(scale('angular', datum.key)) < 0",
                  "signal": "-5 + (radius + 11) * sin(scale('angular', datum.key))"
                },
                {
                  "signal": "(radius + 11) * sin(scale('angular', datum.key))"
                }
              ],
              "text": {
                "field": "key"
              },
              "align": {
                "value": "center"
              },
              "baseline": [{
                  "test": "scale('angular', datum.key) > 0",
                  "value": "top"
                },
                {
                  "test": "scale('angular', datum.key) == 0",
                  "value": "middle"
                },
                {
                  "value": "bottom"
                }
              ],
              "fill": {
                "value": "black"
              },
              "fontSize": {
                "value": valueLabeltext
              }
            }
          }
        },
        {
          "type": "line",
          "name": "twenty-line",
          "from": {
            "data": "keys"
          },
          "encode": {
            "enter": {
              "interpolate": {
                "value": "linear-closed"
              },
              "x": {
                "signal": "0.2 * radius * cos(scale('angular', datum.key))"
              },
              "y": {
                "signal": "0.2 * radius * sin(scale('angular', datum.key))"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        },
        {
          "type": "line",
          "name": "fourty-line",
          "from": {
            "data": "keys"
          },
          "encode": {
            "enter": {
              "interpolate": {
                "value": "linear-closed"
              },
              "x": {
                "signal": "0.4 * radius * cos(scale('angular', datum.key))"
              },
              "y": {
                "signal": "0.4 * radius * sin(scale('angular', datum.key))"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        },
        {
          "type": "line",
          "name": "sixty-line",
          "from": {
            "data": "keys"
          },
          "encode": {
            "enter": {
              "interpolate": {
                "value": "linear-closed"
              },
              "x": {
                "signal": "0.6 * radius * cos(scale('angular', datum.key))"
              },
              "y": {
                "signal": "0.6 * radius * sin(scale('angular', datum.key))"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        },
        {
          "type": "line",
          "name": "eighty-line",
          "from": {
            "data": "keys"
          },
          "encode": {
            "enter": {
              "interpolate": {
                "value": "linear-closed"
              },
              "x": {
                "signal": "0.8 * radius * cos(scale('angular', datum.key))"
              },
              "y": {
                "signal": "0.8 * radius * sin(scale('angular', datum.key))"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        },
        {
          "type": "line",
          "name": "outer-line",
          "from": {
            "data": "radial-grid"
          },
          "encode": {
            "enter": {
              "interpolate": {
                "value": "linear-closed"
              },
              "x": {
                "field": "x2"
              },
              "y": {
                "field": "y2"
              },
              "stroke": {
                "value": "lightgray"
              },
              "strokeWidth": {
                "value": 1
              }
            }
          }
        }
      ]
    }
  };

  const elem = document.createElement("div");
  elem.setAttribute("style", "display: inline-block; width: 250px; height: 300px; font-size: initial;");

  const chart = new google.visualization.VegaChart(elem);
  chart.draw(dataTable, options);

  document.getElementById(chartId).appendChild(elem);
}


</script>

レーダーチャートのカスタマイズ

よく使う設定項目を変数にしてまとめました。

データの種類やデザインにあわせて変更してみてください。

チャートデータを編集する

スクリプト
// レーダーチャートのデータ
  const chartData = [
    ["radar_1","iPhone 12 の満足度", "#B82E2E", [
      ["デザイン", 4.54],
      ["携帯性", 4.31],
      ["レスポンス", 4.80],
      ["画面表示", 4.69],
      ["バッテリー", 4.23],
      ["カメラ", 4.53]
    ]],
    ["radar_1","iPhone 13 の満足度", "#B82E2E", [
      ["デザイン", 4.43],
      ["携帯性", 3.96],
      ["レスポンス", 4.54],
      ["画面表示", 4.49],
      ["バッテリー", 4.37],
      ["カメラ", 4.27]
    ]],
    ["radar_2","iPhone SE(第2世代) の満足度", "#6633CC", [
      ["デザイン", 4.24],
      ["携帯性", 4.67],
      ["レスポンス", 4.64],
      ["画面表示", 4.17],
      ["バッテリー", 3.49],
      ["カメラ", 3.98]
    ]],
    ["radar_2","iPhone SE(第3世代) の満足度", "#6633CC", [
      ["デザイン", 3.71],
      ["携帯性", 4.39],
      ["レスポンス", 4.79],
      ["画面表示", 3.51],
      ["バッテリー", 3.28],
      ["カメラ", 3.45]
    ]],
  ];

レーダーチャートのデータを指定します。

データの構造とチャートとの対応は下のイラストをご覧ください。

コードのデータ構造と表示されるチャートの関係
スクリプト
["radar_1","iPhone 12 の満足度", "#B82E2E", [

1行目は、チャートを表示するブロックのID、レーダーチャートのタイトル、色を指定します。

コード例に沿って解説します。

“radar_1″がブロックIDです。

「iPhone 12」と「iPhone 13」は、同じブロックで並べて表示させるため同じIDである「radar_1」を割り当てています。

異なるIDを指定することで、同じ記事の中でID毎にDIVブロックを置くことができます。

“iPhone 12の満足度”がレーダーチャートのタイトルです。長すぎると見切れますのでご注意ください。

“#B82E2E”が色です。カラーコードで指定します。

スクリプト
    ["デザイン", 3.71],
    ["携帯性", 4.39],
    ["レスポンス", 4.79],
    ["画面表示", 3.51],
    ["バッテリー", 3.28],
    ["カメラ", 3.45]

2行目以降は、チャートのラベルと値を指定します。

この例では項目は6つですが、この部分を行単位で増やしたり減らしたりすることで、項目数を変更することができます。

値のスケール

スクリプト
// 値スケール
const valueScale = [0, 5];

レーダーチャートの最小値と最大値を指定します。1つ目の数値が最小値、2つ目の数値が最大値です。

この例では、最小値が「0」、最大値が「5」です。

通常、レーダーチャートの中心はゼロですので、最小値は「0」のままにし、データに合わせて最大値を調整します。

レーダーチャート 値のスケールの設定例

パーセント表示したい場合は、最大値を「1」にすると100%になります。

値のフォーマット

スクリプト
// 値フォーマット
const valueFormat = '1';

値の表示形式を設定します。

この例では、通常の数値形式となります。

パーセント表示したい場合は、’1%’を指定します。

レーダーの枠線の太さ

スクリプト
// レーダーの枠線の太さ
const valueStrokeWidth = 1.5;

レーダーの枠線の太さを設定します。

単位はピクセルです。

レーダーチャート 枠線の太さの設定例

レーダーの領域の不透明度

スクリプト
// レーダーの領域の不透明度
const valueOpacity = 0.1;

レーダーの領域部分の不透明度を設定します。

「0.0~1.0」までの数値で不透明度を指定します。数値が大きいほど不透明度が高くなり、よりはっきりと表示されます。

  • 不透明度: 1 ー 完全に不透明な状態になります。
  • 不透明度: 0 ー 完全に透明な状態になります。
レーダーチャート 領域の不透明度の設定例

不透明度は枠線には適用されません。

フォントサイズ

スクリプト
// レーダーの値のフォントサイズ
const valueValtext = 14;
// レーダーのラベルのフォントサイズ
const valueLabeltext = 12;

値のフォントサイズと、ラベルのフォントサイズをそれぞれ設定します。

レーダーチャート フォントサイズの設定例

レーダーチャートの活用例

レーダーチャートの活用例を紹介します。

レーダーチャートは良くも悪くも存在感があるため、使いどころが難しいです。

比較したい目的に応じた適切な評価項目とデータを用意することが重要です。

能力値のレーダーチャート

【例】ガンダム登場人物の能力値

人事評価やストレスチェックの結果を視覚的に表現したい場合、レーダーチャートは最適な方法のひとつになります。

この例は、「ギレンの野望」というゲームのキャラクターの能力値を示したものです。

このグラフの設定は以下のとおりです。

スクリプト
  // 値スケール
  const valueScale = [0, 25];
  // 値フォーマット
  const valueFormat = '1';
  // レーダーの枠線の太さ
  const valueStrokeWidth = 3;
  // レーダーの領域の不透明度
  const valueOpacity = 0.5;
  // レーダーの値のフォントサイズ
  const valueValtext = 14;
  // レーダーのラベルのフォントサイズ
  const valueLabeltext = 12;

ちなみに、レーダーの3つの色「黄・青・赤」はガンダムのトリコロールカラーを使いました。

色使いに迷った場合は、モビルスーツのカラーリングを参考にしてみてはいかがでしょうか?

配色パターンガンダム一年戦争編 配色パターンはガンダムのカラーリングでキメる|一年戦争編

評価項目の多いレーダーチャート

【例】食料自給率(2020年カロリーベース)

「チャートデータを編集する」で解説したように、データ項目は増やすことができます。

この例では、12項目をレーダーチャートで表現しています。

食料自給率のデータは、農林水産省WEBサイト「日本の食料自給率」にある「令和2年度食料自給率について」を参照しました。

要素を重ねて表示するレーダーチャート

【例】テストの平均点と自分の点数を比較するレーダーチャート

このレーダーチャートの作り方は、こちらの記事をご覧ください。

【コピペでGoogleCharts】重ねて表示するレーダーチャートの作り方

このグラフを導入しているブロガーさん

ブログのなかで、レーダーチャートを使っているブロガーさんの記事を紹介します。

たけゆうさん「技術士ノート」

技術士の特化ブログを運営している、たけゆうさん@takeyuublog のブログです。

技術士講座の添削結果をレーダーチャートで表示させています。

ゆーさん「転職逆転人生」

転職のノウハウを発信している、ゆーさん@yusan60857558 のブログです。

レーダーチャートを使って転職ツールをわかりやすく評価しています。

レーダーチャート活用のお手本のような記事ですので、見ておいて損はありませんよ。

まとめ

レーダーチャートを使うことで、複数の評価項目をわかりやすく表現することができます。

ブログの中にレーダーチャートを使って、ライバルに差をつけましょう。

レーダーチャート以外のグラフの使い方やデザイン集は、以下の記事をご覧ください。

wordpressブログにグラフを埋めこむためのGoogleChartsの使い方 WordPressブログにグラフを埋めこむためのGoogleChartsの使い方

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA