【R】ggplotとdendextendできれいなデンドログラムを描く!

  • 2020-10-01
  • 2020-10-01
  • R
  • 5703View
  • 0件
R NO IMAGE

デンドログラムって見た目のカスタマイズがすごく難しいですよね。。。R標準のplotだとダサいし、かと言ってggplot2で描こうとするとあまりにも難しいし。。。

そこで今回は見た目のカスタマイズがすごく簡単にできて、さらにggplotによる細かい調整も可能な方法を紹介します!

それがggplotとdendextendによる描画です!

具体的には自分で作成するのがとてもむずかしい描画用のデータをdendextendで作成して、そのデータを使ってggplot2で調整して描画していきます!

dendextendで見た目の調整 + 描画用データの作成
ggplot2でタイトルなど細部の調整

この記事では以下のようなデンドログラムのブランチやラベルの色付けやサイズの調整を自在に操れるようになることを目指します!

少し工夫して以下のような放射状のデンドログラム(radial plotといいます!)も後ほど紹介します!

 

準備 treeの作成

まずは描画用のサンプルデータを用意します!

今回はRに標準搭載のデータセットであるUSArrestsデータセットを使って行きます!

library(dendextend)
library(ggplot2)
library(tidyverse)

tree <- USArrests %>% 
  head(20) %>% 
  dist() %>% 
  hclust()

dend <- tree %>% 
  as.dendrogram()

USArrestsの20行だけを使って階層的クラスタリングを行い、ツリーを作成しました!

そしてas.dendrogram()でデンドログラムに変換します!ここでどんなデンドログラムができているのかを確認してみましょう!

as.dendrogram()の出力であるdendrogramオブジェクトはplot()で描画できます

dend %>% 
  plot()

 

見た目もそれなりなデンドログラムが描画できました!細部にこだわらないのであればこれでも十分なクオリティですね!

さてこのデンドログラムをベースにしてラベルや枝の見た目を調整していきましょう!

dendextendによる装飾

どうやってデンドログラムの見た目を変更するの?

dendextedライブラリはset()関数によって直感的にかつとても簡単にデンドログラムの見た目の変更ができます!

では実際にやってみましょう!

以下のコードはk=3でk-meansクラスタリングを行って、クラスターごとに枝に色付けを行っています!

dend %>% 
  set('branches_k_color', k=3) %>% 
  plot()

クラスターごとに色分けされて見やすいデンドログラムができました!上のコードにset(‘branches_k_color’, k=3)を加えるだけでこれだけの変更ができてしまいます!

デンドログラムはset()関数を使って見た目を調整する!

set()関数の使いかた

set()関数の引数は以下の3つです!

set(object, what, value)

object: デンドログラムオブジェクト(上のコードだとdend)
what: 第一引数で渡したデンドログラムオブジェクトのどのプロパティを変更するかを決める。あとで詳しく説明します!
value: whatで選択したプロパティをどのように変更するか

上のコードでも使ったようにset(dend, ‘branches_k_color’, k=3)のように使用します!(わかりやすいように%>%を使わずに書きました!)
ここで曲者なのがwhatの部分でかなりの量の選択肢があります。全部で27個もあります笑
すべてを説明するのはあまりにも長くなるので詳細についてはdendextendのvignette (https://cran.r-project.org/web/packages/dendextend/vignettes/dendextend.html)を参考にしてください!
whatは文字列で渡すのですが、基本的には'{デンドログラムの部位}_{変更するプロパティ}’という形で渡すことになります!
例えばデンドログラムの’ラベル’の’色’を変更したいならばwhat=’labels_colors’を渡します!
デンドログラムの部位はlabels, leaves, nodesの3つ、
変更するプロパティはcol (色), cex (ラベルのサイズ), pch (ポイントの形),  lwd (先の太さ), lty (線の種類)などがあります!

他にもhang_leavesやclear_branchesみたいな'{デンドログラムの部位}_{変更するプロパティ}’の形に当てはまらないものもありますが使用するときに適宜調べられれば問題ないと思います!

さて、それではsetを使ってデンドログラムを自分好みに変えていくことにしましょう!

ラベル、ブランチの見た目の調整

# クラスタリング
cluster <- cutree(tree=tree,k=4)
n_cluster <- length(table(cluster))
cluster <- cluster[order.dendrogram(dend)]

# カラーパレットの作成
cluster_color_palette <- viridis::plasma(n_cluster)
cluster_color <- cluster_color_palette[cluster]
names(cluster_color) <- names(cluster)

# デンドログラムのカスタマイズ
dend<- dend %>% 
  set("labels_colors", cluster_color[names(cluster)]) 
for (i in seq_len(n_cluster)){
  dend <- dend %>% 
    set("by_labels_branches_col", 
        names(cluster[cluster == i]),
        TF_values = cluster_color_palette[i]
    )
}
plot(dend, horiz = FALSE)

今度はクラスタリングも自分で行ってみました!カラーパレットも作成して、各クラスターに任意の色を割り当てています!

1回のfor ループで一つのクラスターの枝の色を割り当てています!

set(“by_labels_branches_col”, names(cluster[cluster == i]), TF_values = cluster_color_palette[i] )

この部分の”by_labels_branches_col”はラベルを明示的に指定して、そのラベルに至るまでの枝の色を変更することができます!i番目のクラスターにはカラーパレットのi番目の色で塗ってねということを指定しています!

for ループとset(“by_labels_branches_col”)を用いればほとんどどんな場合にも自分の好きな色を好きな位置に塗ることができるのでかなりオススメな方法です!

リーフの見た目の調整

ラベルとbranch以外の部分も変更してみましょう!

dend %>% 
  set("leaves_pch", 16) %>% 
  set("leaves_cex", 1.5) %>% 
  set("leaves_col", cluster_color) %>% 
  plot()

“leaves_pch”, “leaves_cex”, “leaves_col”,でそれぞれ葉の部分(枝の末端部分)の’シェイプ’、’サイズ’、’色’をそれぞれ指定しています!ラベルや枝の色と合わせるとなかなか綺麗になりますね!

ノードの見た目の調整

今度はデンドログラムのノード(分岐点)にも上と同じようなオブジェクトを置いてみます!

dend %>% 
  set("nodes_pch", 15) %>% 
  set("nodes_cex", 1.2) %>% 
  set("nodes_col", "orange") %>% 
  plot()

これも上と同様に”nodes_pch”, “nodes_cex”, “nodes_col”で’ノードのシェイプ’、’サイズ’、’色’をそれぞれ指定しています!

 

オブジェクトの追加(カラーバー、長方形型の網掛け)

さて!次はこれにカラーバーを追加してみます!

plot(dend, horiz = FALSE) 
colored_bars(colors = cluster_color, dend = dend, rowLabels = "cluster", 
              sort_by_labels_order = FALSE, y_scale=10, y_shift=-125)

plotで先程のデンドログラムを描画したあとにcolored_bars()を追加するだけです!めっちゃ簡単ですね!

次は強調したい部分に長方形で網掛けしてみます!

target_leaf <- 13
plot(dend, horiz = FALSE) 
rect.dendrogram( dend, k=4, lty = 5, lwd = 0, x=target_leaf, col=rgb(0.050, 0.031, 0.53, 0.1) ) 

これもplotで先程のデンドログラムを描画したあとにrect.dendrogram()を追加するだけです!k=4とx=target_leafという引数を渡していますが、これはk=4でk-means clusteringをして、13番目の葉が含まれているクラスターに長方形の網掛けをするということを指定しています!

ちょっと違う長方形でもやってみましょう!

target_leaf <- 8
plot(dend, horiz = FALSE) 
rect.dendrogram(dend, k=4, x = target_leaf, border = 8, lty = 5, lwd = 2)

今度はborder = 8, lty = 5を指定してみました!ボーダーの色と線の種類が変わっていますね!

 

ggplot2との併用

これまでのplotだけでも十分に美しいデンドログラムが描けましたが、ggplot2を利用することでより細かい部分にまでこだわった描画を行えます!

どうやってggplot2とdendextendを組み合わせるの?

 

1. as.ggdend()でデンドログラムオブジェクト(上のコードのdend)から描画用のデータフレームを作成する
2. tidyverse系の関数でデータフレームを編集
3. データフレームを使ってggplot2で描画!

キーになるのがas.ggdend()関数でdendオブジェクトから描画用データの含まれたデータフレームを一発で生成できることです!

データフレームにしてしまった後はdplyrなどのデータフレーム編集用の関数を使って必要な列を追加したり値を変更したりすることでかなり細かな見た目の調整を行うことができます!

おそらくコードを見るのが一番理解しやすいと思いますので実際にやってみます!

gdend <- as.ggdend(dend)
names(gdend)
#  [1] "segments" "labels" "nodes" 

as.ggdendでdendオブジェクトをggdendクラスオブジェクトに変換します!

ggdendクラスオブジェクは”segments” “labels” “nodes”の3つのデータフレームを保持しておりそれぞれが編集可能です!

早速これらを編集してみましょう!

gdend$labels <- gdend$labels %>% 
  mutate(cluster_name = cluster[as.character(label)],
col = cluster_color[as.character(label)])

gdend$segments <- gdend$segments %>% 
  mutate(col = if_else(is.na(col), 'grey', col))

gdend$labels$angle <- 90

gdend$labelsにはクラスターの名前とクラスターの色の列を追加してみました!

gdend$segmentsはcolの列にNAが含まれていたのでこれを’grey’に変更してあげます。

ラベルを90°回転して表示したかったのでgdend$labels$angle <- 90でangleの列を追加して90を代入してあげます!

準備ができたのでこのデータフレームのデータを使ってggplot2で描画してみます!

ggplot()+
  geom_segment(data = gdend$segments,
    aes(x = x, y = y, xend = xend, yend = yend, col=col)) + 
  geom_text(data = gdend$labels,
    aes(x = x, y = y, label=label, col=col, angle=angle), hjust=1.1) +
  theme_minimal()+ 
  theme(legend.position = "none",
    axis.line.x=element_blank(),
    axis.text.x=element_blank(),
    axis.ticks.x=element_blank(),
    axis.title.x=element_blank(),
    panel.grid.minor.x=element_blank(),
    panel.grid.major.x=element_blank(),
    axis.title.y=element_blank()) + 
  scale_color_identity() +
  ylim(-100, 300) 

 

 

 

さきほどplotで描画したものを今度はggplot2で描画してみました!

ggplot2を使えばplotでは難しい背景の透過ができたり、テーマを指定することで簡単に見た目を変えたり、axis ticksなどの細部にも変更を加えることができます!

ついでなので上でやったカラーバーもggplot2で再現してみます!geom_rectを使えば簡単にできてしまいます!

gdend$labels$hadjust <- 100
colorbar_width <- 15
ggplot()+
  geom_segment(data = gdend$segments,
    aes(x = x, y = y, xend = xend, yend = yend, col=col)) + 
  geom_text(data = gdend$labels,
    aes(x = x, y = y, label=label, col=col, angle=angle), hjust=1.1) +
  geom_rect(data = gdend$labels,
    aes(xmin = x -0.5, xmax = x + 0.5, 
      ymin = y - hadjust - colorbar_width, ymax = y - hadjust, 
      fill=col, col=col)) +
  theme_minimal()+ 
  theme(legend.position = "none",
    axis.line.x=element_blank(),
    axis.text.x=element_blank(),
    axis.ticks.x=element_blank(),
    axis.title.x=element_blank(),
    panel.grid.minor.x=element_blank(),
    anel.grid.major.x=element_blank(),
    axis.title.y=element_blank()) + 
  scale_color_identity() +
  scale_fill_identity() +
  ylim(-120, 300)

 

放射状のデンドログラム(Radial Plot)

最初に紹介した放射状に広がるデンドログラムRadial Plotを描画してみます!

ggplot2でscale_y_reverse()とcoord_polar(theta=”x”)によってy座標の反転と、x軸をもとにした極座標表示に切り替えることで描画することができます!

gdend_circle <- dend %>% 
  set("nodes_pch", 15)  %>% 
  set("nodes_cex", 1.2) %>% 
  set("nodes_col", "orange") %>% 
  as.ggdend()

ggplot(gdend_circle, labels = FALSE) + 
  scale_y_reverse()+
  coord_polar(theta="x")

やっぱりラベルがある方が見た目もいいのでちょっと頑張って調整してみます!

ラベルの角度の調整に少し工夫が必要ですが以下のようなものを描画できます!

gdend_circle$labels <- gdend_circle$labels %>% 
  mutate(angle = (90 -  360 * x / (max(x) + 1)))

ggplot() + 
  geom_segment(data = gdend$segments,
               aes(x = x, y = y, xend = xend, yend = yend, col=col)) + 
  geom_text(data = gdend_circle$labels, 
            aes(x = x, y = y - 10 , label=label, col=col, angle = angle),hjust=0 ) +
  scale_x_continuous(expand = c(0,1))+
  scale_y_reverse(expand = c(0,100)) +
  coord_polar(theta="x") +
  theme_minimal()+ 
  theme(legend.position = "none",
        axis.line.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        panel.grid.minor.x=element_blank(),
        panel.grid.major.x=element_blank(),
        axis.title.y=element_blank()) + 
  scale_color_identity()

論文などでも見かけるレベルのプロットができました!これは見た目も非常に綺麗でかなりオススメな描画方法なのでぜひ使ってみてください!

2つのデンドログラムの比較!Tanglegramの描画

タングルグラムって何?

あまり聞いたことがないかもしれませんが、タングルグラムとは2つのデンドログラムを比較するためのもので、ラベルの同じ2つのデンドログラムを並べて同一のラベル同士を線でつないだものです!

すぐにサンプルを出しますが、例えばUSArrestsデータセットに対して階層的クラスタリングを行うとします。

そこで2つの異なる階層的クラスタリングのアルゴリズムを使って作成した2つのデンドログラムの結果を比較したいというときにタングルグラムは非常に便利です!

以下でその例を見てみましょう!

#ward.D2アルゴリズムで階層的クラスタリング
dend_wd2 <- USArrests %>% 
  head(20) %>% 
  dist() %>% 
  hclust(method="ward.D2") %>% 
  as.dendrogram() %>% 
  set("branches_k_color", k=4)

#medianアルゴリズムで階層的クラスタリング
dend_median <- USArrests %>% 
  head(20) %>% 
  dist() %>% 
  hclust(method="median") %>% 
  as.dendrogram() %>% 
  set("branches_k_color", k=4)

dl <- dendlist(dend_wd2, dend_median)
tanglegram(dl, sort = TRUE, common_subtrees_color_lines = FALSE, highlight_distinct_edges  = FALSE)

かなり複雑な描画ですが、コード自体はすごく簡単です!

今回はdend_wd2とdend_medianという2つの異なるデンドログラムを作成してその比較を行っています!

タングルグラムの描画はdendlist()に2つのデンドログラムを渡してdendlistオブジェクトを作成します!そしてdendlistオブジェクトをtanglegram()に渡せば上のようなプロットができます!

1.dendlist()に2つのデンドログラムを渡してdendlistオブジェクトを作成
2.dendlistオブジェクトをtanglegram()にわたす!

tanglegram()のオプションを設定して見た目を調整してみましょう!

tanglegram(dl, sort = TRUE, common_subtrees_color_lines = TRUE, highlight_distinct_edges = TRUE)

 

まとめ

今回は以上です!dendeextendでブランチやノード、ラベルの描画用データを作成、ggplot2で細部まで見た目を調整して描画という組み合わせは非常に便利なのでぜひ使ってみてください!

 

参照

https://cran.r-project.org/web/packages/dendextend/vignettes/dendextend.html

https://www.r-graph-gallery.com/340-custom-your-dendrogram-with-dendextend.html

https://cran.r-project.org/web/packages/ggdendro/vignettes/ggdendro.html

http://www.sthda.com/english/wiki/beautiful-dendrogram-visualizations-in-r-5-must-known-methods-unsupervised-machine-learning

NO IMAGE
最新情報をチェックしよう!