树状图(或树形图)是一种网络结构。它由一个根节点组成,根节点产生由边或分支连接的多个节点。层次结构的最后一个节点称为叶。本文主要基于R语言实现树形图的绘制。关于python实现树形图的绘制见:基于matplotlib实现树形图的绘制

之所以还用R语言实现树形图的绘制,主要原因在于R语言所实现的树形图比python实现的更加多样。R语言树形图提供以下两种类型:

  1. 分层树形图:类似CEO管理团队领导管理员工等等。
  2. 聚类树形图:聚类将一组个体按相似性分组。它的结果可以可视化为一棵树。

本文主要参考:Dendrogram

本文所有代码见:R-Study-Notes


1 分层树形图 DENDROGRAM FROM HIERARCHICAL DATA

1.1 基于R语言和ggraph绘制树形图 Introduction to tree diagram with R and ggraph

本节逐步介绍通过R语言和ggraph建立树形图,并提供了解释和可复制代码。ggraph包是用R从层次数据构建树形图的最佳选择,其遵循与ggplot2相同的逻辑。本节旨在使用ggraph库制作一个表示层次数据的基本树形图。考虑两种输入格式:

  • 基于边列表
  • 基于嵌套数据

1.1.1 通过边绘制树形图 Dendrogram from edge list

基于边列表绘制树形图意思是给定每一个节点到另外一个节点的数据,来依次绘制树形图。边列表数据使用ggraph最方便的格式。数据结构如下图所示。每一行代表一条边,比如(origin,group1)表示从节点origin到group的边。

请遵循以下步骤:

  • 使用igraph库中的graph_from_data_frame()函数将输入数据帧转换为图形对象
  • 使用ggraph的树形图布局,布局为'dendrogram'

主要步骤依次讲解:

创建数据

其中d1为根节点到第一层节点的数据,每一行代表一条边,比如(origin,group1)表示从节点origin到group的边,d2是第一层节点到第二层节点的数据。edges是对d1和d2的汇总

# libraries
# 包
library(ggraph)
library(igraph)
library(tidyverse) # create an edge list data frame giving the hierarchical structure of your individuals
# 创建层级数据
d1 <- data.frame(from="origin", to=paste("group", seq(1,3), sep=""))
d1
d2 <- data.frame(from=rep(d1$to, each=3), to=paste("subgroup", seq(1,9), sep="_"))
d2
# 汇总
edges <- rbind(d1, d2)
edges
A data.frame: 3 × 2
from to
<fct> <fct>
origin group1
origin group2
origin group3
A data.frame: 9 × 2
from to
<fct> <fct>
group1 subgroup_1
group1 subgroup_2
group1 subgroup_3
group2 subgroup_4
group2 subgroup_5
group2 subgroup_6
group3 subgroup_7
group3 subgroup_8
group3 subgroup_9
A data.frame: 12 × 2
from to
<fct> <fct>
origin group1
origin group2
origin group3
group1 subgroup_1
group1 subgroup_2
group1 subgroup_3
group2 subgroup_4
group2 subgroup_5
group2 subgroup_6
group3 subgroup_7
group3 subgroup_8
group3 subgroup_9

创建图形结构

需要创建专用的图形结构,origin->group1表示从节点origin到节点group1

# Create a graph object
mygraph <- graph_from_data_frame( edges )
mygraph
IGRAPH 2c80675 DN-- 13 12 --
+ attr: name (v/c)
+ edges from 2c80675 (vertex names):
[1] origin->group1 origin->group2 origin->group3 group1->subgroup_1
[5] group1->subgroup_2 group1->subgroup_3 group2->subgroup_4 group2->subgroup_5
[9] group2->subgroup_6 group3->subgroup_7 group3->subgroup_8 group3->subgroup_9

绘图

# Basic tree
# 基础树形图
# layout表示布局方式,circular表示是否为环状树形图
ggraph(mygraph, layout = 'dendrogram', circular = FALSE) +
# 画边
geom_edge_diagonal() +
# 画节点
geom_node_point() +
# 设置主题
theme_void()

1.1.2 通过嵌套数据绘制树形图 Dendrogram from a nested dataframe

另一种常见格式是嵌套数据。下面的代码演示如何轻松地将数组转换为嵌套数据。嵌套数据结构如下图所示,嵌套数据每一列代表一个节点,行代表节点到节点的路径

建立数据

# libraries
library(ggraph)
library(igraph)
library(tidyverse) # create a data frame
data <- data.frame(
level1="CEO",
level2=c( rep("boss1",4), rep("boss2",4)),
level3=paste0("mister_", letters[1:8])
)
data
A data.frame: 8 × 3
level1 level2 level3
<fct> <fct> <fct>
CEO boss1 mister_a
CEO boss1 mister_b
CEO boss1 mister_c
CEO boss1 mister_d
CEO boss2 mister_e
CEO boss2 mister_f
CEO boss2 mister_g
CEO boss2 mister_h

将数据转换为边列表

# transform it to a edge list!
edges_level1_2 <- data %>% select(level1, level2) %>% unique %>% rename(from=level1, to=level2)
edges_level2_3 <- data %>% select(level2, level3) %>% unique %>% rename(from=level2, to=level3)
edges_level1_2
edges_level2_3
edge_list=rbind(edges_level1_2, edges_level2_3)
edge_list
A data.frame: 2 × 2
from to
<fct> <fct>
1 CEO boss1
5 CEO boss2
A data.frame: 8 × 2
from to
<fct> <fct>
boss1 mister_a
boss1 mister_b
boss1 mister_c
boss1 mister_d
boss2 mister_e
boss2 mister_f
boss2 mister_g
boss2 mister_h
A data.frame: 10 × 2
from to
<fct> <fct>
1 CEO boss1
5 CEO boss2
11 boss1 mister_a
2 boss1 mister_b
3 boss1 mister_c
4 boss1 mister_d
51 boss2 mister_e
6 boss2 mister_f
7 boss2 mister_g
8 boss2 mister_h

绘图

# Now we can plot that
mygraph<- graph_from_data_frame( edge_list )
ggraph(mygraph, layout = 'dendrogram', circular = FALSE) +
geom_edge_diagonal() +
geom_node_point() +
theme_void()

1.2 使用R和ggraph自定义树形图 Dendrogram customization with R and ggraph

本节旨在显示了如何自定义树形图:布局,边线样式,节点特征等

1.2.1 数据准备 Data preparation

这里准备的是本节所用到的通用数据

首先使用igraph包创建一个数据集和一个图形对象

# Libraries
library(ggraph)
library(igraph)
library(tidyverse)
theme_set(theme_void()) # data: edge list
# 边数据
d1 <- data.frame(from="origin", to=paste("group", seq(1,7), sep=""))
d2 <- data.frame(from=rep(d1$to, each=7), to=paste("subgroup", seq(1,49), sep="_"))
edges <- rbind(d1, d2)
Warning message:
"New theme missing the following elements: axis.title.x, axis.title.x.top, axis.title.y, axis.title.y.right, axis.text.x, axis.text.x.top, axis.text.y, axis.text.y.right, axis.ticks, axis.line, axis.line.x, axis.line.y, legend.background, legend.margin, legend.spacing, legend.spacing.x, legend.spacing.y, legend.key, legend.key.height, legend.key.width, legend.text.align, legend.title.align, legend.direction, legend.justification, legend.box.margin, legend.box.background, legend.box.spacing, panel.background, panel.border, panel.spacing.x, panel.spacing.y, panel.grid, panel.grid.minor, plot.background, strip.background, strip.placement, strip.text.x, strip.text.y"

为每个节点添加聚类信息和值信息

# We can add a second data frame with information for each node!
# 为每个节点设置信息
name <- unique(c(as.character(edges$from), as.character(edges$to)))
# 设置每个节点对应的聚类信息和值
vertices <- data.frame(
name=name,
group=c( rep(NA,8) , rep( paste("group", seq(1,7), sep=""), each=7)),
cluster=sample(letters[1:4], length(name), replace=T),
value=sample(seq(10,30), length(name), replace=T)
)
vertices[0:10,]
# Create a graph object
mygraph <- graph_from_data_frame( edges, vertices=vertices)
A data.frame: 10 × 4
name group cluster value
<fct> <fct> <fct> <int>
origin NA b 11
group1 NA c 25
group2 NA c 10
group3 NA d 28
group4 NA b 25
group5 NA d 25
group6 NA c 26
group7 NA b 30
subgroup_1 group1 a 10
subgroup_2 group1 d 11

1.2.2 环形或线形布局 Circular or linear layout

首先,由于ggraph的layout参数,您可以使用circular选项来使用环形或线形布局。

# 线形布局
ggraph(mygraph, layout = 'dendrogram', circular = FALSE) +
geom_edge_diagonal()
# 环形布局
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
geom_edge_diagonal()

1.2.3 边的样式 Edge style

然后你可以选择不同的边样式。ggraph软件包有两个主要功能:geom_edge_link和geom_edge_diagram。

# 折线
ggraph(mygraph, layout = 'dendrogram') +
geom_edge_link()
# 弧线
ggraph(mygraph, layout = 'dendrogram') +
geom_edge_diagonal()

1.2.4 标签和节点 Labels and Nodes

您可能需要添加标签,以便对树有更深入的了解。最后是节点。这可以分别使用geom_node_text和geom_node_point来完成。但是对于环形树添加标签比较麻烦,下一节单独进行讲述。

ggraph(mygraph, layout = 'dendrogram') +
# 设置边
geom_edge_diagonal() +
# 设置节点名,label表示节点名,filter=leaf表示跳过叶子节点,angle标签方向,hjust和nudge_y标签和节点距离
geom_node_text(aes( label=name, filter=leaf) , angle=90 , hjust=1, nudge_y = -0.01) +
# 设置y轴范围
ylim(-.4, NA) ggraph(mygraph, layout = 'dendrogram') +
geom_edge_diagonal() +
geom_node_text(aes( label=name, filter=leaf) , angle=90 , hjust=1, nudge_y = -0.04) +
# 为每个节点添加点
geom_node_point(aes(filter=leaf) , alpha=0.6) +
ylim(-.5, NA)

1.2.5 自定义美学 Customize aesthetics

在树形图中添加颜色或形状是一项常见的任务。它可以更清楚地显示数据集的组织结构。ggraph的工作原理与ggplot2相同。在每个组件的美学部分,可以使用初始数据帧的一列映射到形状、颜色、大小或其他。

ggraph(mygraph, layout = 'dendrogram') +
geom_edge_diagonal() +
geom_node_text(aes( label=name, filter=leaf, color=group) , angle=90 , hjust=1, nudge_y=-0.1) +
geom_node_point(aes(filter=leaf, size=value, color=group) , alpha=0.6) +
ylim(-.6, NA) +
theme(legend.position="none")

1.3 基于R和ggraph自定义环形树形图

本节介绍通过R和ggraph自定义环形树形图。ggraph库的圆形树形图应有其专用页面,因为调整标签可能有些棘手。实际上,它们需要具有良好的角度,可以在图表的左侧上下翻转,并且还需要调整其对齐方式。以下分布介绍:

创建数据

# Libraries
library(ggraph)
library(igraph)
library(tidyverse)
library(RColorBrewer) # 创建数据,类似前面的步骤
# create a data frame giving the hierarchical structure of your individuals
d1=data.frame(from="origin", to=paste("group", seq(1,5), sep=""))
d2=data.frame(from=rep(d1$to, each=5), to=paste("subgroup", seq(1,25), sep="_"))
edges=rbind(d1, d2)
# create a vertices data.frame. One line per object of our hierarchy
# 为每个节点添加值
vertices = data.frame(
name = unique(c(as.character(edges$from), as.character(edges$to))),
# 正态分布随机取值,共获得31个值。如果是其他数据,去掉value = runif(31),查看运行后的dim(vertices)就知道该填多少了
value = runif(31)
)
# Let's add a column with the group of each name. It will be useful later to color points
# 为每个节点添加分组信息
vertices$group = edges$from[ match( vertices$name, edges$to ) ]
dim(vertices)
head(vertices)
  1. 31
  2. 3
A data.frame: 6 × 3
name value group
<fct> <dbl> <fct>
origin 0.2694659 NA
group1 0.6816846 origin
group2 0.2849697 origin
group3 0.2955677 origin
group4 0.6879641 origin
group5 0.2655517 origin

添加绘图信息

# Let's add information concerning the label we are going to add: angle, horizontal adjustement and potential flip calculate the ANGLE of the labels
# 让我们添加有关我们将要添加的标签的信息:角度、水平调整和翻转,计算标签的角度
# 添加id值
vertices$id=NA
myleaves=which(is.na( match(vertices$name, edges$from) ))
nleaves=length(myleaves)
vertices$id[ myleaves ] = seq(1:nleaves)
# 添加角度
vertices$angle= -360 * vertices$id / nleaves
vertices
A data.frame: 31 × 5
name value group id angle
<fct> <dbl> <fct> <int> <dbl>
origin 0.26946595 NA NA NA
group1 0.68168456 origin NA NA
group2 0.28496969 origin NA NA
group3 0.29556769 origin NA NA
group4 0.68796411 origin NA NA
group5 0.26555169 origin NA NA
subgroup_1 0.13447919 group1 1 -14.4
subgroup_2 0.87993752 group1 2 -28.8
subgroup_3 0.73281460 group1 3 -43.2
subgroup_4 0.05199267 group1 4 -57.6
subgroup_5 0.95072049 group1 5 -72.0
subgroup_6 0.67968533 group2 6 -86.4
subgroup_7 0.60904665 group2 7 -100.8
subgroup_8 0.91107152 group2 8 -115.2
subgroup_9 0.56348062 group2 9 -129.6
subgroup_10 0.78231794 group2 10 -144.0
subgroup_11 0.39831777 group3 11 -158.4
subgroup_12 0.39330663 group3 12 -172.8
subgroup_13 0.57479330 group3 13 -187.2
subgroup_14 0.61543980 group3 14 -201.6
subgroup_15 0.05581496 group3 15 -216.0
subgroup_16 0.34000915 group4 16 -230.4
subgroup_17 0.65765123 group4 17 -244.8
subgroup_18 0.63469281 group4 18 -259.2
subgroup_19 0.41069057 group4 19 -273.6
subgroup_20 0.07418380 group4 20 -288.0
subgroup_21 0.23007252 group5 21 -302.4
subgroup_22 0.86334833 group5 22 -316.8
subgroup_23 0.01567696 group5 23 -331.2
subgroup_24 0.53860661 group5 24 -345.6
subgroup_25 0.74063768 group5 25 -360.0
# calculate the alignment of labels: right or left
# 判断标签是偏向左边还是右边
# hjust表示是否水平翻转
vertices$hjust<-ifelse(vertices$angle < -90 & vertices$angle > -270, 1, 0) # flip angle BY to make them readable
# 是否翻转标签
vertices$angle<-ifelse(vertices$angle < -90 & vertices$angle > -270, vertices$angle+180, vertices$angle)
vertices[12:20,]
# Create a graph object
# 创建图
mygraph <- graph_from_data_frame( edges, vertices=vertices )
A data.frame: 9 × 6
name value group id angle hjust
<fct> <dbl> <fct> <int> <dbl> <dbl>
12 subgroup_6 0.6796853 group2 6 -86.4 0
13 subgroup_7 0.6090466 group2 7 79.2 1
14 subgroup_8 0.9110715 group2 8 64.8 1
15 subgroup_9 0.5634806 group2 9 50.4 1
16 subgroup_10 0.7823179 group2 10 36.0 1
17 subgroup_11 0.3983178 group3 11 21.6 1
18 subgroup_12 0.3933066 group3 12 7.2 1
19 subgroup_13 0.5747933 group3 13 -7.2 1
20 subgroup_14 0.6154398 group3 14 -21.6 1
vertices
A data.frame: 31 × 6
name value group id angle hjust
<fct> <dbl> <fct> <int> <dbl> <dbl>
origin 0.26946595 NA NA NA NA
group1 0.68168456 origin NA NA NA
group2 0.28496969 origin NA NA NA
group3 0.29556769 origin NA NA NA
group4 0.68796411 origin NA NA NA
group5 0.26555169 origin NA NA NA
subgroup_1 0.13447919 group1 1 -14.4 0
subgroup_2 0.87993752 group1 2 -28.8 0
subgroup_3 0.73281460 group1 3 -43.2 0
subgroup_4 0.05199267 group1 4 -57.6 0
subgroup_5 0.95072049 group1 5 -72.0 0
subgroup_6 0.67968533 group2 6 -86.4 0
subgroup_7 0.60904665 group2 7 79.2 1
subgroup_8 0.91107152 group2 8 64.8 1
subgroup_9 0.56348062 group2 9 50.4 1
subgroup_10 0.78231794 group2 10 36.0 1
subgroup_11 0.39831777 group3 11 21.6 1
subgroup_12 0.39330663 group3 12 7.2 1
subgroup_13 0.57479330 group3 13 -7.2 1
subgroup_14 0.61543980 group3 14 -21.6 1
subgroup_15 0.05581496 group3 15 -36.0 1
subgroup_16 0.34000915 group4 16 -50.4 1
subgroup_17 0.65765123 group4 17 -64.8 1
subgroup_18 0.63469281 group4 18 -79.2 1
subgroup_19 0.41069057 group4 19 -273.6 0
subgroup_20 0.07418380 group4 20 -288.0 0
subgroup_21 0.23007252 group5 21 -302.4 0
subgroup_22 0.86334833 group5 22 -316.8 0
subgroup_23 0.01567696 group5 23 -331.2 0
subgroup_24 0.53860661 group5 24 -345.6 0
subgroup_25 0.74063768 group5 25 -360.0 0
# Make the plot
p<-ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
# 设置边
geom_edge_diagonal(colour="grey") +
# 设置边的颜色
scale_edge_colour_distiller(palette = "RdPu") +
# 设置点的标签
geom_node_text(aes(x = x*1.15, y=y*1.15, filter = leaf, label=name, angle = angle, hjust=hjust, colour=group), size=2.7, alpha=1) +
# 设置点的形状
geom_node_point(aes(filter = leaf, x = x*1.07, y=y*1.07, colour=group, size=value, alpha=0.2)) +
# 控制颜色
scale_colour_manual(values= rep( brewer.pal(9,"Paired") , 30)) +
scale_size_continuous( range = c(0.1,10) ) +
theme_void() +
theme(
# 不显示图例
legend.position="none",
plot.margin=unit(c(0,0,0,0),"cm"),
) +
expand_limits(x = c(-1.3, 1.3), y = c(-1.3, 1.3))
p
# 保存数据 Save at png
ggsave(p, file="output.png", width=10, height=10,dpi=300)

另外对于标签角度的设置多说几句,不同的平台标签角度设置不一样。标签的角度设置主要有以下三行代码:

# 添加角度
vertices$angle= -360 * vertices$id / nleaves
# hjust表示是否水平翻转
vertices$hjust<-ifelse(vertices$angle < -90 & vertices$angle > -270, 1, 0)
# 是否翻转标签
vertices$angle<-ifelse(vertices$angle < -90 & vertices$angle > -270, vertices$angle+180, vertices$angle)

第一行代码指的是给每个标签赋予一个角度值,通常设置这一行,其他两行不设置,或者跳过,图形基本上就会完成。只不过在环形左半边标签是翻转的,就是字朝下。如果要字朝上就设置先水平反正左边的标签,然后180度旋转左边的标签,右边标签不变就行了。

比如通过第一行我们获得的角度值,subgroup_7到subgroup_18处于左半边,角度其实范围为-90到-270度,所以通过第二行和第三行代码只要设置-90度到-270度的点,水平翻转然后翻转标签就行了。

2 聚类结果的树形图 DENDROGRAM FROM CLUSTERING RESULT.

层次聚类是数据科学中的一项常见任务,可以使用R中的hclust()函数来执行。下面的示例将指导您完成整个过程,演示如何准备数据、如何运行聚类以及如何构建适当的图表以可视化其结果。

2.1 用R进行聚类的最基本树形图 Most basic dendrogram for clustering with R

聚类允许通过相似性将样本分组,并且其结果可以可视化为树形图。这篇文章描述了该hclust()函数的基本用法,并根据其输出构建树形图。对于层次聚类树形图有以下极大要素:

  • 输入数据集是一个矩阵,其中每一行是一个样本,每一列是一个变量。可以使用t()函数转置矩阵。
  • 聚类是在提供样本之间距离的正方形矩阵(sample x sample)上执行的,距离矩阵可以使用dist()或cor()函数计算,具体取决于您提出的问题
  • hclust()函数用于执行分层聚类
  • 它的输出可以用plot()函数直接可视化。请参阅可能的自定义。

首先产生数据集

# Dataset
data <- matrix( sample(seq(1,2000),200), ncol = 10 )
rownames(data) <- paste0("sample_" , seq(1,20))
colnames(data) <- paste0("variable",seq(1,10))
data
dim(data)
A matrix: 20 × 10 of type int
variable1 variable2 variable3 variable4 variable5 variable6 variable7 variable8 variable9 variable10
sample_1 49 863 888 361 1285 1695 258 821 459 1715
sample_2 251 673 1096 963 1874 1837 876 1329 1565 1286
sample_3 156 220 73 726 1356 1951 108 751 1218 823
sample_4 1241 363 367 1097 847 275 1415 582 646 711
sample_5 533 1006 440 1962 510 70 732 5 584 899
sample_6 1443 1758 204 1216 1248 307 1072 1975 719 1776
sample_7 412 8 1983 665 197 1347 612 656 557 186
sample_8 1856 1850 548 957 150 296 405 1340 1088 672
sample_9 994 1171 233 1656 1732 953 1651 918 60 1676
sample_10 715 272 368 670 688 1743 724 1956 897 1974
sample_11 820 1374 934 65 842 1269 917 581 324 1
sample_12 1692 915 944 824 164 378 1439 1298 270 389
sample_13 128 707 286 444 1893 1179 28 778 1172 916
sample_14 805 1847 308 1536 1008 236 1631 628 1943 1270
sample_15 1585 997 1933 1135 651 1447 1598 402 1205 339
sample_16 151 216 427 735 773 1001 684 1700 1639 1782
sample_17 408 1303 449 1906 1965 752 381 1637 1894 1524
sample_18 257 1859 1871 81 1696 1886 1774 1845 839 152
sample_19 840 1240 1188 437 1125 256 960 1401 193 1552
sample_20 1902 1087 1112 1481 353 407 199 71 547 404
  1. 20
  2. 10
# Euclidean distance
# 计算欧式距离
dist <- dist(data[ , c(4:8)] , diag=TRUE) # Hierarchical Clustering with hclust
# 分层聚类
hc <- hclust(dist) # Plot the result
plot(hc)

对于层次聚类主要有以下几个原则:

  • 基于目标之间的距离。
  • 寻找两个目标之间的最小距离。
  • 将两个目标对象聚合在一个簇中。
  • 用目标群的中心进行计算。直到只有一个簇包含每个点。

2.2 放大分支 Zoom on a group

我们可以放大树的特定部分。使用[[ ]]运算符选择感兴趣的枝条。例如:

# 将上面的树形图存入dhc
dhc <- as.dendrogram(hc)
dhc[[1]] 表示从上到下第一层,其中从左往右第一个枝条
dhc[[2]][[2]] 表示从上到下第二层,其中从左往右第二个枝条

下面代码,所示展示2.1节所画层次树第一层右边部分分支

# store the dedrogram in an object
# 保存聚类结果为dhc变量
dhc <- as.dendrogram(hc) # set the margin
par(mar=c(4,4,2,2))
# 打印会告诉你分支情况
print(dhc[[2]])
# Plot the Second group
# 绘图
plot(dhc[[2]] , main= "zoom on a part of the dendrogram")
'dendrogram' with 2 branches and 14 members total, at height 2795.492

下面代码,所示展示2.1节所画层次树第一层右边部分的第二个分支

# store the dedrogram in an object
dhc <- as.dendrogram(hc) # set the margin
par(mar=c(4,4,2,2)) print(dhc[[2]][[1]])
# Plot the Second group
plot(dhc[[2]][[1]] , main= "zoom on a part of the dendrogram")
'dendrogram' with 2 branches and 9 members total, at height 2107.407

2.3 绘制带颜色和图例的树形图 Dendrogram with color and legend in R

本节主要讲述基本树状图的自定义。展示了如何为叶子和样本名称添加特定的颜色。它允许检查在聚类之后是否确实找到了预期的类。

首先生成数据

# Build dataset (just copy and paste, this is NOT interesting)
# 生成数据,可以跳过
sample <- paste(rep("sample_",24) , seq(1,24) , sep="")
specie <- c(rep("dicoccoides" , 8) , rep("dicoccum" , 8) , rep("durum" , 8))
treatment <- rep(c(rep("High",4 ) , rep("Low",4)),3)
data <- data.frame(sample,specie,treatment)
for (i in seq(1:5)){
gene=sample(c(1:40) , 24 )
data=cbind(data , gene)
colnames(data)[ncol(data)]=paste("gene_",i,sep="")
}
data[data$treatment=="High" , c(4:8)]=data[data$treatment=="High" , c(4:8)]+100
data[data$specie=="durum" , c(4:8)]=data[data$specie=="durum" , c(4:8)]-30
rownames(data) <- data[,1]
head(data)
A data.frame: 6 × 8
sample specie treatment gene_1 gene_2 gene_3 gene_4 gene_5
<fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
sample_1 sample_1 dicoccoides High 126 133 110 111 135
sample_2 sample_2 dicoccoides High 130 130 111 121 113
sample_3 sample_3 dicoccoides High 124 135 115 125 140
sample_4 sample_4 dicoccoides High 111 109 135 135 132
sample_5 sample_5 dicoccoides Low 20 34 9 17 37
sample_6 sample_6 dicoccoides Low 32 26 21 1 24

然后聚类

# Compute Euclidean distance between samples
dist=dist(data[ , c(4:8)] , diag=TRUE) # Perfor clustering with hclust
# 聚类并保存结果
hc <- hclust(dist)
dhc <- as.dendrogram(hc)
dhc
'dendrogram' with 2 branches and 24 members total, at height 328.8632

对于每个节点都有自己的属性

# Actually, each leaf of the tree has several attributes, like the color, the shape.. Have a look to it:
# 选择特别的节点
specific_leaf <- dhc[[1]][[1]][[1]]
specific_leaf
attributes(specific_leaf)
'dendrogram' with 2 branches and 2 members total, at height 23.81176
$members
2
$midpoint
0.5
$height
23.8117617995813
$class
'dendrogram'

创建改变叶子节点属性函数

如果想给树的每片叶子上色,必须改变每片叶子的属性。这可以使用dendrapply函数来完成。因此,创建了一个函数,向叶子节点添加属性。如果应用自己的数据,改变treatment和specie的值就行了。

i=0
colLab<-function(n)
{
# 判断是否为节点
if(is.leaf(n))
{
# 获得节点的属性
a=attributes(n) # I deduce the line in the original data, and so the treatment and the specie.
# 获得该点的信息
ligne=match(attributes(n)$label,data[,1])
# 根据自己的结果设置
treatment=data[ligne,3];
if(treatment=="Low"){col_treatment="blue"};if(treatment=="High"){col_treatment="red"}
# 根据种类设置颜色,根据自己的结果设置
specie=data[ligne,2];
if(specie=="dicoccoides"){col_specie="red"};if(specie=="dicoccum"){col_specie="Darkgreen"};if(specie=="durum"){col_specie="blue"} # M odification of leaf attribute
# 修改节点的属性
attr(n,"nodePar")<-c(a$nodePar,list(cex=1.5,lab.cex=1,pch=20,col=col_treatment,lab.col=col_specie,lab.font=1,lab.cex=1))
}
return(n)
}

绘图

# 应用函数
dL <- dendrapply(dhc, colLab) # And the plot
plot(dL , main="structure of the population")
# 图例
legend("topright",
# 文字
legend = c("High Nitrogen" , "Low Nitrogen" , "Durum" , "Dicoccoides" , "Dicoccum"),
# 颜色
col = c("red", "blue" , "blue" , "red" , "Darkgreen"),
pch = c(20,20,4,4,4), bty = "n", pt.cex = 1.5, cex = 0.8 ,
text.col = "black", horiz = FALSE, inset = c(0, 0.1))

3 使用DENDEXTEND绘制树形图 MORE CUSTOMIZATION WITH DENDEXTEND

dendextend主要是自定义层次聚类图,对第二节的补充。dendextend包允许在树状图定制方面更进一步。这里有一组例子展示了主要的可能性,比如在底部添加颜色条,面对面绘制2棵树等等。

3.1 基础树形图绘制 Basic dendrogram

DENDEXTEND首先需要绘制如下最基本的树形图,然后进行相应更改

# Library
library(tidyverse) # Data
head(mtcars) # Clusterisation using 3 variables
# 聚类,使用管道
mtcars %>%
select(mpg, cyl, disp) %>%
dist() %>%
hclust() %>%
as.dendrogram() -> dend # Plot
# 绘图
par(mar=c(7,3,1,1)) # Increase bottom margin to have the complete label
plot(dend)
A data.frame: 6 × 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

3.2 set函数 The set() function

dendextend的set()函数允许修改树的特定部分的属性。例如,您可以为分支和标签自定义cex、lwd、col、lty。也可以自定义节点或叶。下面的代码说明了这一概念:

自定义树枝和标签

# library
library(dendextend) # 绘图dend是设置函数
dend %>%
# Custom branches
# 自定义树枝的颜色
set("branches_col", "red") %>%
# 自定义树枝宽度
set("branches_lwd", 3) %>%
# Custom labels
# 自定义标签颜色
set("labels_col", "blue") %>%
# 自定义标签字体大小
set("labels_cex", 0.8) %>%
plot()

自定义树枝节点

dend %>%
# 自定义树枝节点形状
set("nodes_pch", 20) %>%
# 自定义树枝节点大小
set("nodes_cex", 1.5) %>%
# 自定义树枝节点颜色
set("nodes_col", "red") %>%
plot()

自定义叶子

dend %>%
# 最后一层节点形状
set("leaves_pch", 22) %>%
# 最后一层节点宽度
set("leaves_cex", 1) %>%
# 最后一层节点颜色
set("leaves_col", "red") %>%
plot()

3.3 聚类结果突出 Highlight clusters

dendextend库有一些很好的功能来突出树簇。可以根据分支的簇属性为分支和标签上色,指定所需的簇数。这个 rect.dendrogram()函数甚至允许用矩形突出显示一个或多个特定的簇。

基于颜色突出聚类结果


par(mar=c(1,1,1,7))
dend %>%
# 根据第一层分支结果自定义标签颜色
set("labels_col", value = c("skyblue", "orange", "grey"), k=3) %>%
# 根据第一层分支结果自定义分支颜色
set("branches_k_color", value = c("skyblue", "orange", "grey"), k = 3) %>%
# horize是否水平放置,axes是否显示旁边的距离尺
plot(horiz=TRUE, axes=FALSE)
# 画线条,v高度,lty线条类型
abline(v = 350, lty = 2)

基于矩形框突出聚类结果

# 使用
par(mar=c(9,1,1,1))
dend %>%
set("labels_col", value = c("skyblue", "orange", "grey"), k=3) %>%
set("branches_k_color", value = c("skyblue", "orange", "grey"), k = 3) %>%
plot(axes=FALSE)
# 画矩形框
# k表示将类切割为k个簇,lty矩形框线条类型,lwd矩形框线条宽度,col填充颜色,x表示从第几个类开始画簇
rect.dendrogram( dend, k=3, lty = 2, lwd = 5, x=17, col=rgb(0.1, 0.2, 0.4, 0.1) )

3.4 与预期的聚类结果相比较 Comparing with an expected clustering

将得到的集群与预期的分布进行比较是一项常见的任务。在我们用来构建树状图的mtcars数据集中,有一个am列是一个二进制变量。如果我们可以用cluster()函数来检查与这个变量是否一致。


# Create a vector of colors, darkgreen if am is 0, green if 1.
# 获得数据,如果am为0就是forestgreen颜色
my_colors <- ifelse(mtcars$am==0, "forestgreen", "green") # Make the dendrogram
# 设置图像空白区域
par(mar=c(10,1,1,1))
dend %>%
set("labels_col", value = c("skyblue", "orange", "grey"), k=3) %>%
set("branches_k_color", value = c("skyblue", "orange", "grey"), k = 3) %>%
set("leaves_pch", 19) %>%
set("nodes_cex", 0.7) %>%
plot(axes=FALSE,horiz =FALSE) # Add the colored bar
# 添加颜色bar
# colors颜色,dend聚类图,rowLabels名字
colored_bars(colors = my_colors, dend = dend, rowLabels = "am",horiz =FALSE)

3.5 基于tanglegram()比较2个树状图 Comparing 2 dendrograms with tanglegram()

可以使用tanglegram()函数比较两个树状图。这里它说明了一个非常重要的概念:当你计算你的距离矩阵和当你运行你的层次聚类算法时,你不能简单地使用默认选项而不考虑你在做什么。看看两种不同的集群化方法之间的区别吧。

# Make 2 dendrograms, using 2 different clustering methods
# 使用两种完全不同的聚类方法
d1 <- USArrests %>% dist() %>% hclust( method="average" ) %>% as.dendrogram()
d2 <- USArrests %>% dist() %>% hclust( method="complete" ) %>% as.dendrogram() # Custom these kendo, and place them in a list
# 定制树列表
dl <- dendlist(
d1 %>%
set("labels_col", value = c("skyblue", "orange", "grey"), k=3) %>%
set("branches_lty", 1) %>%
set("branches_k_color", value = c("skyblue", "orange", "grey"), k = 3),
d2 %>%
set("labels_col", value = c("skyblue", "orange", "grey"), k=3) %>%
set("branches_lty", 1) %>%
set("branches_k_color", value = c("skyblue", "orange", "grey"), k = 3)
) # Plot them together
tanglegram(dl,
# 子树是否带颜色
common_subtrees_color_lines = FALSE,
# 是否突出显示边
highlight_distinct_edges = TRUE,
# 是否突出分支
highlight_branches_lwd=FALSE,
# 两个树的距离
margin_inner=7,
# 两个树之间线条宽度
lwd=2
)

4 参考

[R语言] 基于R语言实现树形图的绘制的更多相关文章

  1. [R语言] 基于R语言实现环状条形图的绘制

    环状条形图(Circular barplot)是条形图的变体,图如其名,环状条形图在视觉上很吸引人,但也必须小心使用,因为环状条形图使用的是极坐标系而不是笛卡尔坐标系,每一个类别不共享相同的Y轴.环状 ...

  2. 《R语言入门》语言及环境简单介绍

    简单介绍 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/diss ...

  3. 概率图模型 基于R语言 这本书中的第一个R语言程序

    概率图模型 基于R语言 这本书中的第一个R语言程序 prior <- c(working =0.99,broken =0.01) likelihood <- rbind(working = ...

  4. 基于R语言的时间序列指数模型

    时间序列: (或称动态数列)是指将同一统计指标的数值按其发生的时间先后顺序排列而成的数列.时间序列分析的主要目的是根据已有的历史数据对未来进行预测.(百度百科) 主要考虑的因素: 1.长期趋势(Lon ...

  5. 基于R语言的ARIMA模型

    A IMA模型是一种著名的时间序列预测方法,主要是指将非平稳时间序列转化为平稳时间序列,然后将因变量仅对它的滞后值以及随机误差项的现值和滞后值进行回归所建立的模型.ARIMA模型根据原序列是否平稳以及 ...

  6. Twitter基于R语言的时序数据突变检测(BreakoutDetection)

    Twitter开源的时序数据突变检测(BreakoutDetection),基于无参的E-Divisive with Medians (EDM)算法,比传统的E-Divisive算法快3.5倍以上,并 ...

  7. R语言基于S4的面向对象编程

    前言 本文接上一篇文章 R语言基于S3的面向对象编程,本文继续介绍R语言基于S4的面向对象编程. S4对象系统具有明显的结构化特征,更适合面向对象的程序设计.Bioconductor社区,以S4对象系 ...

  8. 30个深度学习库:按Python、C++、Java、JavaScript、R等10种语言分类

    30个深度学习库:按Python.C++.Java.JavaScript.R等10种语言分类 包括 Python.C++.Java.JavaScript.R.Haskell等在内的一系列编程语言的深度 ...

  9. 【R笔记】R语言函数总结

    R语言与数据挖掘:公式:数据:方法 R语言特征 对大小写敏感 通常,数字,字母,. 和 _都是允许的(在一些国家还包括重音字母).不过,一个命名必须以 . 或者字母开头,并且如果以 . 开头,第二个字 ...

随机推荐

  1. 0025:2011年NOIp普及组真题——瑞士轮题解

    题目链接:https://www.luogu.com.cn/problem/P1309 如果是新手可能马上会想到sort排序,每比一次就排一次,但是这样的时间复杂度有点高,只有60分: 这是因为每次比 ...

  2. dubbo的一系列配置与搭建

    dubbo新的版本采用前后端分离技术,在github上下载的时候,不仅仅只是一个dubbo-admin 而是将admin包分离为dubbo-admin-ui前端包和dubbo-admin-server ...

  3. AI之强化学习、无监督学习、半监督学习和对抗学习

    1.强化学习 @ 目录 1.强化学习 1.1 强化学习原理 1.2 强化学习与监督学习 2.无监督学习 3.半监督学习 4.对抗学习 强化学习(英语:Reinforcement Learning,简称 ...

  4. Hugging Face发布diffuser模型AI绘画库初尝鲜!

    作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 TensorFlow 实战系列:https://www.showmeai ...

  5. 「MySQL高级篇」MySQL之MVCC实现原理&&事务隔离级别的实现

    大家好,我是melo,一名大三后台练习生,死去的MVCC突然开始拷打我! 引言 MVCC,非常顺口的一个词,翻译起来却不是特别顺口:多版本并发控制. 其中多版本是指什么呢?一条记录的多个版本. 并发控 ...

  6. java代码整洁之道

    package Day01;import org.junit.Test;import java.text.NumberFormat;import java.util.Scanner;public cl ...

  7. 驱动开发:内核封装WSK网络通信接口

    本章LyShark将带大家学习如何在内核中使用标准的Socket套接字通信接口,我们都知道Windows应用层下可直接调用WinSocket来实现网络通信,但在内核模式下应用层API接口无法使用,内核 ...

  8. costool - 腾讯云cos快捷工具。

    目录 使用截图 使用方法 配置文件 安装方法 其他 一个腾讯云cos(对象存储)非官方快速上传和下载的工具,使用官方go-sdk二次开发.可以用于以下场景. 备份一些配置文件,比如.bashrc .v ...

  9. Linux---ls cd

    ls 命令 ls命令是linux下最常用的命令,是 list 的缩写,可以用各种方式查看目录中的内容. 格式: ls [选项] [目录名] 常用参数 short long function -a -- ...

  10. vue传值

    在vue 中组件间的传参是必不可少的,下面说下几种传参方式 1.父组件传值给子组件,首先父组件发送的形式是用bind(用缩写:)绑定值到子组件身上.然后子组件用属性props接收 2.子组件传值父组件 ...