決定木の可視化において、とても柔軟性が高いggpartyパッケージをご紹介します。

ggpartyパッケージは、ggplot2の機能をpartykitに拡張し、partyクラスのツリーオブジェクトのために明瞭に構造化され、高度にカスタマイズ可能なビジュアライゼーションを作成するために必要なツールを提供します。

ggpartyパッケージを用いると、ノードやエッジに対して様々な設定をすることで多様な表現が可能になります。
特に強力なのは最下段のノードにおいて、分類木の場合は通常であれば目的変数の100%積み上げ棒グラフとなりますが、個数の積み上げ棒グラフにしたり、ある説明変数でグループ化なども可能になります。
同様に、回帰木の場合は通常であれば目的変数の箱ひげ図となりますが、散布図にしたり、ある説明変数でグループ化なども可能になります。

ここでは簡単のため、rpartパッケージのrpart関数の結果オブジェクトをpartykitパッケージのas.party関数を用いてpartyクラスのツリーオブジェクトに変換したものを用います。

分類木

サンプルデータとして、Rに標準で含まれているTitanicを用います。
最初に必要なパッケージのロードとサンプルデータを扱いやすい形に変更しておきます。


library(rpart)
library(partykit)
library(ggplot2)
library(ggparty)

tmp <- data.frame(Titanic)
df <- data.frame(
  Class = rep(tmp$Class, tmp$Freq),
  Sex = rep(tmp$Sex, tmp$Freq),
  Age = rep(tmp$Age, tmp$Freq),
  Survived = rep(tmp$Survived, tmp$Freq)
)

head関数を用いてdfを確認しておきます。


head(df)

結果は次になります。


  Class  Sex   Age Survived
1   3rd Male Child       No
2   3rd Male Child       No
3   3rd Male Child       No
4   3rd Male Child       No
5   3rd Male Child       No
6   3rd Male Child       No

次に、Survivedを目的変数、ClassとSex、Ageを説明変数として分類木をrpart関数を用いて実行し、結果をctに格納します。
また、この結果をas.party関数を用いてpartyクラスのツリーオブジェクトに変換します。


ct <- rpart(Survived ~ Class + Sex + Age , data = df)
pct <- as.party(ct)

ggpartyパッケージのggparty関数やgeom_edge関数などを用いて可視化します。


g <- ggparty(pct, terminal_space = 0.5)
g <- g + geom_edge(size = 1.5)
g <- g + geom_edge_label(colour = "grey", size = 6)
g <- g + geom_node_plot(
  gglist = list(geom_bar(aes(x = "", fill = Survived), position = "fill"), theme_bw(base_size = 15)),
  scales = "fixed",
  id = "terminal",
  shared_axis_labels = TRUE,
  shared_legend = TRUE,
  legend_separator = TRUE,
)
g <- g + geom_node_label(
  aes(col = splitvar),
  line_list = list(aes(label = paste("Node", id)),
                   aes(label = splitvar)),
  line_gpar = list(list(
    size = 12,
    col = "black",
    fontface = "bold"
  ),
  list(size = 20)),
  ids = "inner"
)
g <- g + geom_node_label(
  aes(label = paste0("Node ", id, ", N = ", nodesize)),
  fontface = "bold",
  ids = "terminal",
  size = 5,
  nudge_y = 0.01
)
g <- g + theme(legend.position = "none")
plot(g)

可視化されたグラフは次になります。

回帰木

サンプルデータとして、rpartパッケージに含まれているcu.summaryを用います。
最初に必要なパッケージのロードしておきます。


library(rpart)
library(partykit)
library(ggplot2)
library(ggparty)

head関数を用いてcu.summaryを確認しておきます。


head(cu.summary)

結果は次になります。


> head(cu.summary)
                Price Country Reliability Mileage  Type
Acura Integra 4 11950   Japan Much better      NA Small
Dodge Colt 4     6851   Japan              NA Small
Dodge Omni 4     6995     USA  Much worse      NA Small
Eagle Summit 4   8895     USA      better      33 Small
Ford Escort   4  7402     USA       worse      33 Small
Ford Festiva 4   6319   Korea      better      37 Small

次に、Priceを目的変数、MileageとCountry、Typeを説明変数として回帰木をrpart関数を用いて実行し、結果をrtに格納します。
また、この結果をas.party関数を用いてpartyクラスのツリーオブジェクトに変換します。


rt <- rpart(Price ~ Mileage + Country + Type, data = cu.summary)
prt <- as.party(rt)

ggpartyパッケージのggparty関数やgeom_edge関数などを用いて可視化します。
ここでは、表現力の自由度を確認するために、最下段のノードにおいて、Type別に箱ひげ図を表示するように設定しました。


g <- ggparty(prt, terminal_space = 0.5)
g <- g + geom_edge(size = 1.5)
g <- g + geom_edge_label(colour = "grey", size = 3)
g <- g + geom_node_plot(
  gglist = list(geom_boxplot(aes(x = "", y = Price, fill = Type)), theme_bw(base_size = 12)),
  scales = "fixed",
  id = "terminal",
  shared_axis_labels = TRUE,
  shared_legend = TRUE,
  legend_separator = TRUE,
)
g <- g + geom_node_label(
  aes(col = splitvar),
  line_list = list(aes(label = paste("Node", id)),
                   aes(label = splitvar)),
  line_gpar = list(list(
    size = 10,
    col = "black",
    fontface = "bold"
  ),
  list(size = 12)),
  ids = "inner"
)
g <- g + geom_node_label(
  aes(label = paste0("Node ", id, ", N = ", nodesize)),
  fontface = "bold",
  ids = "terminal",
  size = 3,
  nudge_y = 0.01
)
g <- g + theme(legend.position = "none")
plot(g)

可視化されたグラフは次になります。

補足

ここでは、いくつかの補足事項をお伝えさせていただきます。

エッジラベルは回転させることはできない

ggpartyのVersion 1.0.0では、エッジのラベルを回転させることはできません。
これは、ggpartyの該当ソースコードの259行目にあるgeom_edge_label関数を見るとgeom_label関数が使用されており、ggplot2のgeom_label関数のリファレンスを見ると、geom_label関数はangleをサポートしていないことが確認できます。

エッジのラベルを個別に移動することはできない

ggpartyのVersion 1.0.0では、エッジのラベルをgeom_edge_label関数の引数nudge_xとnudge_yを用いて移動させることができます。
しかし、この方法はエッジのラベルに対して個別に指定できず、全体が対象となります。

分類木の終点ノードのy軸をパーセント表示にする

ソースコードは、次になります。
上記の分類木のコードとの相違点は、geom_node_plot関数の引数gglistのlist内です。


g <- ggparty(pct, terminal_space = 0.5)
g <- g + geom_edge(size = 1.5)
g <- g + geom_edge_label(colour = "grey", size = 6)
g <- g + geom_node_plot(
  gglist = list(geom_bar(aes(x = "", fill = Survived), position = "fill"),
                theme_bw(base_size = 15),
                ylab("Percent"),
                scale_y_continuous(labels = scales::percent)),
  scales = "fixed",
  id = "terminal",
  shared_axis_labels = TRUE,
  shared_legend = TRUE,
  legend_separator = TRUE,
)
g <- g + geom_node_label(
  aes(col = splitvar),
  line_list = list(aes(label = paste("Node", id)),
                   aes(label = splitvar)),
  line_gpar = list(list(
    size = 12,
    col = "black",
    fontface = "bold"
  ),
  list(size = 20)),
  ids = "inner"
)
g <- g + geom_node_label(
  aes(label = paste0("Node ", id, ", N = ", nodesize)),
  fontface = "bold",
  ids = "terminal",
  size = 5,
  nudge_y = 0.01
)
g <- g + theme(legend.position = "none")
plot(g)

分類木の終点ノードの積み上げ棒グラフ内にパーセント表示することはできない

ggpartyのVersion 1.0.0では、ソースコードを確認すると分類木の終点ノードの積み上げ棒グラフ内にパーセント表示することは、おそらくできません。

最後に

ggpartyパッケージを簡単にご紹介させていただきました。
ここでは、棒グラフgeom_barや箱ひげ図geom_boxplotを用いましたが、散布図やヒストグラムなども用いることが可能です。
これらはggplot2パッケージの関数ですので、ggplot2の扱いに慣れていれば、ここでご紹介させていただいたグラフよりも強力な可視化が可能になります。
決定木の可視化にお役に立てたならば幸いです。

参考

関連する記事

  • R データフレームのファクター列を2値に変換する方法 Rのデータフレームにおいて、ファクター列を2値に変換する方法をお伝えいたします。 方法はとても単純で、データフレームの列ごとにファクター型かどうかをチェックし、ファクター型であればファクターごとに2値の列を新たに作成し追加します。 ソースコードは以下のようになります。 convertFactorToBinary <- function(df, sep = […]
  • R言語 CRAN Task View:臨床試験デザイン、監視、および分析R言語 CRAN Task View:臨床試験デザイン、監視、および分析 CRAN Task View:Clinical Trial Design, Monitoring, and Analysisの英語での説明文をGoogle翻訳を使用させていただき機械的に翻訳したものを掲載しました。 Maintainer: Ed Zhang and Harry G. Zhang Contact: Ed.Zhang.jr at […]
  • RStudioのGlobal Optionsの各種設定RStudioのGlobal Optionsの各種設定 RStudioのGlobal Optionsにどのような内容が記載されているかをお伝えいたします。 RStudioのGlobal Optionsは、メニューバーからToolsを選択して、表示されたポップアップ内にあります。 目次 General: 一般 Code: コード Editing: 編集 Display: 表示 […]
  • R言語 CRAN Task View:実験計画法(DoE)および実験データの分析の設計R言語 CRAN Task View:実験計画法(DoE)および実験データの分析の設計 CRAN Task View: Design of Experiments (DoE) & Analysis of Experimental Dataの英語での説明文をGoogle翻訳を使用させていただき機械的に翻訳したものを掲載しました。 Maintainer: Ulrike Groemping Contact: groemping […]
  • 経営戦略に使えるABC分析の基礎知識と活用法経営戦略に使えるABC分析の基礎知識と活用法 ABC分析は売上に関する経営戦略を立てるうえで、最も基本となる分析手法である。ABC分析とは、販売管理、顧客管理で使われる分析の一つで、ある期間で対象を重要度によって分類することにより現状を把握し易くする分析手法だ。 それでは早速解説していく。 ABC分析の手順 期間を過去一年間、対象を商品、重要度を売上とした場合を例に取り、ABC分析を行う手順を説明していく。 […]
R ggpartyパッケージを用いた決定木の可視化