ひとりマーケティングのためのデータ分析

TOOLS / DATA VISUALIZATION

2時点間の「増減の方向と大きさ」を線の傾きで直感的に比較する、
スロープグラフ作成Excel VBAマクロ。

棒グラフでは埋もれがちな増減の方向と大きさが、線の傾きに現れる。

2026/4/26

晴花

HARUKA

凡例に頼らず、変化を線そのもので語らせる——それがスロープグラフの哲学。

スロープグラフとは

Tufte(1983)の著書 The Visual Display of Quantitative Information で提示された可視化手法です。2時点間の変化を線の傾きで表し、凡例に頼ることなく各要素の名前と値を両端に直接ラベルとして付置するのが特徴です。

傾き
線の傾き一本で「増えた・減った・変わらない」が直感的に伝わる
直接ラベル
凡例不要。要素名と値を両端に配置することで「どの線が何か」問題を解消

このページでは Tufte 自身によるグラフの構造を参考にしながら、VBA で次のスロープグラフを描くことを目的とします。

スロープグラフの完成イメージ
免責事項

掲載のコードは一例です。諸般のデータへの対応や、すべての環境での動作を保証するものではありません。コードおよびマクロの利用により生じた損害・トラブル等について、筆者は一切の責任を負いません。

以下、サブスクリプション版 Excel(ver.2021 以降)を使った手順です。

01

元データ

あるお店に蓄積された6年分の回収済みポイントカードの自由記入欄を解析し、前半3年・後半3年の2期に分けて頻出語(上位20語)を集計したデータです。シート名は「Source」で、左側が前半・右側が後半の集計結果です。

元データ:前半・後半の頻出語集計(Sourceシート)
02

表を統合する

前半・後半の2つの表を1つに統合します。新しいシート「Consolidation」を挿入し、出力先のセル(A1 推奨)をアクティブにしておきます。

新しいシート「Consolidation」を挿入してA1をアクティブに

データ タブ → データツール グループの 統合 をクリックします。

データタブ→統合をクリック

統合の設定 ダイアログで 集計の方法合計 になっていることを確認し、統合元範囲 に「Source」シートの左側の表を指定して 追加。同様に右側の表も追加します。

統合元範囲に左表を指定して追加 右表も追加した後のダイアログ状態

統合の基準上端行左端列 両方にチェックを入れて OK。前半・後半の2つの表が1つに統合されます。

上端行・左端列にチェックを入れてOK 統合後の表(Consolidationシート)
03

棒グラフと比べてみて見えてくること

2時点の量を比較する場合、まず思い浮かぶのは2色の棒グラフです。個別の要素を取り出す用途には向いていますが、「前半3位のワードが後半では何位か」「全体的に伸びたか減ったか」といった俯瞰的な問いには答えにくい構造です。

2色の棒グラフによる前後半比較

これをマーカー付き折れ線グラフに変えて行/列を切り替えると、両時点で順的秩序は保たれます。しかし今度は「どの線がどの要素か」がひどく識別しにくくなります。Tufte のスロープグラフはこの問題を、凡例に頼らず要素名と値を両端のラベルとして直接付置することで解消しています。

折れ線グラフへの変換(線の識別問題が発生)
04

VBE を起動してコードをコピペする

リボンの 開発 タブ → コード グループの Visual Basic をクリックして VBE を起動します。メニューの 挿入標準モジュール でコードウィンドウを表示します。

リボン「開発」タブからVisual Basicを起動 VBEで標準モジュールを挿入

下のコードをすべてコピーし、コードウィンドウに貼り付けます。VBE を閉じます。


Option Explicit
Option Base 1

'===============================================================================
' スロープグラフ 作成マクロ
' サイト     : hitorimarketing.net/tools/vba/slope-graph.html
' 作成者     : hawcas
' 作成年     : 2020
'===============================================================================
'
' 【概要】
'   2時点間の変化を線で結ぶスロープグラフを折れ線グラフベースで生成する。
'   片側の値が空白の系列はマーカーのみ(線なし)で表示し、
'   両側に値がある系列は実線で結ぶ。
'   各系列のデータラベルには「項目名 + 値」を連結したテキストを表示する。
'
' 【使い方】
'   1. 元データ(A 列: 項目名, B 列: 時点1の値, C 列: 時点2の値)を選択する。
'   2. DrawSlopeGraph_Main を実行する。
'
' 【新規シートへの書き出し(データラベル用)】
'   選択範囲の C 列から右 2 列目(E 列相当): 系列番号(1〜size)
'   選択範囲の C 列から右 3 列目(F 列相当): データラベル用テキスト(IF 数式)
'     左端ラベル: 「時点2の値 + スペース + 項目名」
'     右端ラベル: 「項目名 + スペース + 時点1の値」
'
' 【モジュール構成】
'   Public Sub
'     DrawSlopeGraph_Main     メイン処理(グラフ生成・系列スタイル設定)
'     DrawSlopeGraph_Sub1     データラベル用テキストの生成(ワークシート数式を配置)
'     DrawSlopeGraph_Sub2     データラベルの付加(InsertChartField でセル参照を設定)
'
'   Private Sub(内部ユーティリティ)
'     SetMarker   片側が空白の系列をマーカーのみ表示に設定する
'     FillLine    両側に値がある系列を実線表示に設定する
'===============================================================================


'===============================================================================
' Sub : DrawSlopeGraph_Main
' 概要 : メイン処理。
'        選択範囲を元に折れ線グラフを生成し、系列ごとに
'        「実線(FillLine)」または「マーカーのみ(SetMarker)」のスタイルを適用する。
'        その後 Sub1・Sub2 を呼んでデータラベルを追加する。
' 前提 : A 列: 項目名, B 列: 時点1の値, C 列: 時点2の値 の範囲を選択してから実行。
'        1行目はヘッダー行として扱う。
'===============================================================================
Sub DrawSlopeGraph_Main()

Dim target        ' 選択範囲オブジェクト
Dim x As Long, y As Long ' ループカウンタ

Set target = Selection

'--- 折れ線グラフを追加し、系列を行方向(各行 = 1 系列)に設定する ---
ActiveSheet.Shapes.AddChart(xlLine).Select
ActiveChart.PlotBy = xlRows

'--- 系列ごとにスタイルを振り分ける ---
'   B 列または C 列が空白の系列 → マーカーのみ(SetMarker)
'   両列に値がある系列         → 実線(FillLine)
For y = 2 To target.Rows.Count
    If target.Range("b1").Offset(y - 1, 0).Value = "" Or _
        target.Range("c1").Offset(y - 1, 0).Value = "" Then
        Call SetMarker(y)
    Else
        Call FillLine(y)
    End If
Next y

'--- データラベル用テキストの生成とラベルの付加 ---
Call DrawSlopeGraph_Sub1(target)
Call DrawSlopeGraph_Sub2(target)

End Sub


'===============================================================================
' Sub : DrawSlopeGraph_Sub1
' 概要 : データラベル用のテキストをワークシート数式として生成する。
'        系列数 × 2 行分のラベルテキストを選択範囲の右 3〜4 列目に配置する。
'        奇数行 = 左端ラベル(時点2の値 + 項目名)
'        偶数行 = 右端ラベル(項目名 + 時点1の値)
' 引数 : t - DrawSlopeGraph_Main の選択範囲(ByVal)
' 出力 : t.Range("c1").Offset(1, 2) 以降: 系列番号(連番)
'        t.Range("c1").Offset(1, 3) 以降: ラベルテキスト(IF 数式、AutoFill で展開)
'===============================================================================
Sub DrawSlopeGraph_Sub1(ByVal t)

Dim y    As Long
Dim size As Long
size = (t.Rows.Count - 1) * 2 ' ラベル行数 = 系列数 × 2(左端・右端で 1 系列あたり 2 行)

'--- 系列番号を連番で書き出す(DrawSlopeGraph_Sub2 の参照用)---
For y = 1 To size
    t.Range("c1").Offset(y, 2).Value = y
Next y

'--- ラベルテキスト数式を生成して AutoFill で全行に展開する ---
'   ROW() の偶奇でラベルの向き(左端・右端)を切り替える
'     偶数行: 「項目名 + " " + 時点1の値」→ グラフの右端ラベル
'     奇数行: 「時点2の値 + " " + 項目名」→ グラフの左端ラベル
Dim str As String
str = "=IF(MOD(ROW(),2)=0, " & _
    "CONCATENATE(OFFSET($A$1,INT(ROW()/2),0), " & _
    """ "", OFFSET($B$1,INT(ROW()/2),0)), " & _
    "CONCATENATE(OFFSET($C$1,INT(ROW()/2),0), " & _
    """ "", OFFSET($A$1,INT(ROW()/2),0)))"
With t.Range("c1").Offset(1, 3)
    .Formula = str
    .AutoFill Destination:=Range(t.Range("c1").Offset(1, 3), _
        t.Range("c1").Offset(size, 3))
End With

End Sub


'===============================================================================
' Sub : DrawSlopeGraph_Sub2
' 概要 : 各系列にデータラベルを付加し、Sub1 が生成したテキストをセル参照で連動させる。
'        左端ラベルは xlLabelPositionLeft に固定する。
'        フォントサイズ・フォント名は本 Sub 内で直接変更できる。
' 引数 : t - DrawSlopeGraph_Main の選択範囲(ByVal)
'===============================================================================
Sub DrawSlopeGraph_Sub2(ByVal t)

Dim y
Dim size As Long
Dim gObj As ChartObject

Set gObj = ActiveChart.Parent
size = (t.Rows.Count - 1) * 2

Dim cnt As Long  ' 系列インデックス(1 〜 系列数)
Dim str As String

'--- 各系列にラベルテキスト(2行分のセル参照)を InsertChartField で設定する ---
'   Step 2 で奇数行・偶数行をペアとして 1 系列に対応させる
For y = 1 To size Step 2
    cnt = Application.WorksheetFunction.RoundUp(y / 2, 0) ' 系列番号(1 始まり)
    str = "='" & ActiveSheet.Name & "'!" & _
        t.Range("c1").Offset(y, 3).Address & ":" & _
        t.Range("c1").Offset(y + 1, 3).Address ' 奇数行(左端)〜偶数行(右端)のセル範囲

    With gObj.Chart.SeriesCollection(cnt)
        .HasDataLabels = True
        With .DataLabels
            .Format.TextFrame2.TextRange. _
                InsertChartField msoChartFieldRange, str, 0 ' セル参照をラベルに設定
            .ShowValue = False  ' 数値ラベルを非表示(セル参照テキストのみ表示)
            .ShowRange = True
            .Format.TextFrame2.WordWrap = msoFalse ' 折り返しなし
        End With
    End With

    '--- フォントの設定(サイズ・日本語フォント・欧文フォントを変更する場合はここを編集)---
    With gObj.Chart.SeriesCollection(cnt).DataLabels. _
        Format.TextFrame2.TextRange.Font
        .size       = 9
        .NameFarEast = "BIZ UDゴシック" ' 日本語フォント
        .Name        = "Myriad Pro"      ' 欧文フォント
    End With

Next y

'--- 各系列の左端点ラベルを左揃えに設定する ---
size = t.Rows.Count - 1
For y = 1 To size
    gObj.Chart.SeriesCollection(y).Points(1).DataLabel.Position = xlLabelPositionLeft
    ' ラベルの自動サイズ調整を無効にする場合はコメント解除:
    'gObj.Chart.SeriesCollection(y).DataLabels.Format.TextFrame2.AutoSize = msoAutoSizeNone
Next y

End Sub


'===============================================================================
' Sub : SetMarker  [Private]
' 概要 : 指定系列を「マーカーのみ・線なし」に設定する。
'        B 列または C 列が空白で片側の値しかない系列に適用する。
' 引数 : i - 系列番号(FullSeriesCollection のインデックス; Main の y 値と対応)
' 設定値(変更する場合はここを編集):
'   MarkerStyle : xlMarkerStyleDot(点)/ xlMarkerStyleCircle(円形)
'   MarkerSize  : マーカーのサイズ(pt)
'   ForeColor   : マーカーの塗りつぶし色(RGB)
'===============================================================================
Private Sub SetMarker(ByVal i As Long)
With ActiveChart.FullSeriesCollection(i - 1)
    .ChartType               = xlLineMarkers
    .MarkerStyle             = xlMarkerStyleDot ' 変更例: xlMarkerStyleCircle(円形)
    .MarkerSize              = 5
    .Format.Fill.ForeColor.RGB = RGB(0, 0, 0)  ' マーカーの色
    .Format.Line.Visible     = msoFalse         ' 線を非表示
End With
End Sub


'===============================================================================
' Sub : FillLine  [Private]
' 概要 : 指定系列を「実線・マーカーなし」に設定する。
'        B・C 列の両方に値がある系列に適用する。
' 引数 : i - 系列番号(FullSeriesCollection のインデックス; Main の y 値と対応)
' 設定値(変更する場合はここを編集):
'   ForeColor : 線の色(RGB)
'   Weight    : 線の太さ(pt)
'===============================================================================
Private Sub FillLine(ByVal i As Long)
With ActiveChart.FullSeriesCollection(i - 1).Format.Line
    .ForeColor.RGB = RGB(0, 0, 0) ' 線の色
    .Weight        = 1             ' 線の太さ(pt)
End With
End Sub
コードウィンドウにコードをペースト
05

データ範囲を指定してマクロを実行する

「Consolidation」シートで、行ラベル・列ラベルを含むデータ範囲全体を選択しておきます。

Consolidationシートで行・列ラベルを含むデータ範囲を選択

リボンの 開発 タブ → マクロ をクリックし、DrawSlopeGraph_Main を選択して 実行 します。

開発タブ→マクロをクリック DrawSlopeGraph_Mainを選択して実行

元表の右側にデータラベル用の文字列が生成され、グラフが描画されます。この時点では原形なので、次のセクションで調整を加えます。

マクロ実行直後の原形グラフ
06

細部を調整して完成させる

ラベルの重なりを緩和するため、グラフエリアを縦方向に伸長します。次に凡例を削除するとプロットエリアが横に広がります。ラベルの揃えや余白を整えたい場合はプロットエリアの幅も調整します。

グラフエリアを縦方向に伸長 凡例を削除してプロットエリアを広げる プロットエリアの幅を調整してラベル位置を整える

縦軸・横軸・目盛り線を不可視にします(Tufte のいう「非データインク」の除去)。残ったラベルの重なりは、Shift キーで左右をロックしながらマウスでラベルを個別に移動させて手作業で解消します。

縦軸・横軸・目盛り線を不可視に ラベルの重なりを手作業で解消 ラベルの重なりを解消した状態

横軸ラベルをわかりやすい名称に変え、ラベル位置を上部に配置するなど任意の書式設定を加えれば完成です。

スロープグラフの完成

完成したグラフを使うと、「前半3位のワードが後半では何位か」「強く伸びたワード・勢いを失ったワード」「後半に初登場・消滅したワード」「全体の増減の偏り」といった俯瞰的な問いにも素早く答えられます。

晴花