D3.js中的Cluster Dendrogram详解
Posted wan353694124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D3.js中的Cluster Dendrogram详解相关的知识,希望对你有一定的参考价值。
Cluster Dendrogram
今天聊一个简单点的,叫做Cluster Dendrogram。Dendrogram的意思是“树状图”,咦?为什么不叫tree呢?仔细看官网作者对Dendrogram的解释,恍然大悟。官网解释如下:
A dendrogram is a node-link diagram that places leaf nodes of the tree at the same depth.
秒懂,有木有!意思是说,Dendrogram其实是一种树形结构图的特殊情况,特殊之处在于,Dendrogram将树叶都放置在了同一个深度上,而树形结构没有这个要求。话不多说,来张Dendrogram的图片,如下:
从图中可以清楚地看到,dendrogram的特点,那就是,树的叶子节点全部在同一个深度上。
接下来,详细解释一下,D3.js是怎么实现这颗特别的树的。
index.html详解——源码
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node circle
fill: #999;
.node text
font: 10px sans-serif;
.node--internal circle
fill: #555;
.node--internal text
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
.link
fill: none;
stroke: #555;
stroke-opacity: 0.4;
stroke-width: 1.5px;
</style>
<svg width="960" height="2000"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
// 获取svg元素
var svg = d3.select("svg"),
// 获取svg画布的宽度,此处+svg.attr("width")前面的“+”为了确保获取到的宽度是数字
width = +svg.attr("width"),
// 获取svg画布的高度
height = +svg.attr("height"),
// 为svg画布添加一个g元素,并将其向右移动40
g = svg.append("g").attr("transform", "translate(40,0)");
// 定义cluster布局函数tree(),并且设置布局的宽、高
var tree = d3.cluster()
.size([height, width - 160]);
// d3.stratify()函数用来将数据转换为tree布局所需要的格式,例如为数据计算并添加parent,depth,children等信息
var stratify = d3.stratify()
//此处定义节点的parentId的计算方式为:从节点id字段中截取最后一个“.”之前的字符串
.parentId(function(d) return d.id.substring(0, d.id.lastIndexOf(".")); );
//读取数据文件
d3.csv("flare.csv", function(error, data)
if (error) throw error;
// 转换csv文件读取的数据,使数据用于可以进行tree()布局
// 返回的root是一个树结构的数据格式,其中的节点具有:children、data、height、id、depth、parent字段,
// 这些字段都是stratify()函数自动计算并且添加的。非常强大的工具函数啊
var root = stratify(data)
.sort(function(a, b) return (a.height - b.height) || a.id.localeCompare(b.id); );
// 进行tree()布局,此处会自动布局,为数据添加可视化所需要的位置信息
// 所以,调用tree(root)之后,root数据中的节点除了children、data、height、id、depth、
// parent之外,又添加了x,y两个字段信息,表示节点的位置信息
tree(root);
// 绘制节点之间的连接线
var link = g.selectAll(".link")
// d3中descentdants函数用来返回某个结构中所有的节点数组,例如此处root是树形结构的数据,
// 那么调用root.descentdants()之后返回的是root结构中所有节点的一个数组;
// js中的slice()函数从已有的数组中返回指定的元素;
// 因此 root.descendants().slice(1)函数返回root中除了depth 为0的节点之外的所有节点
// 组成的数组,这里要去掉depth为0的节点,是因为,根节点只有和其子节点之间的连线,没有哪个
// 节点指向根节点并和其之间有连线了
.data(root.descendants().slice(1))
.enter().append("path") // 添加path元素用来绘制节点连线
.attr("class", "link")
// 此处通过连线的子节点和父节点的坐标来计算path元素的属性“d”的值,以此来绘制节点之间的连线
// 例如对于第一个节点的第一个子元素来说,返回的d属性为:
// M600,20C100,20 100,492.88969812200304 0,492.88969812200304
.attr("d", function(d)
return "M" + d.y + "," + d.x
+ "C" + (d.parent.y + 100) + "," + d.x
+ " " + (d.parent.y + 100) + "," + d.parent.x
+ " " + d.parent.y + "," + d.parent.x;
);
// 绘制节点
var node = g.selectAll(".node")
// 绑定节点数据
.data(root.descendants())
.enter().append("g")
.attr("class", function(d) return "node" + (d.children ? " node--internal" : " node--leaf"); )
// 根据布局算出的每个节点的坐标位置 来摆放节点
.attr("transform", function(d) return "translate(" + d.y + "," + d.x + ")"; )
// 每个节点用圆来绘制
node.append("circle")
.attr("r", 2.5);
// 为节点绑定文字描述
node.append("text")
.attr("dy", 3)
// 若节点有子节点,那么文字在节点的左边,否则在右边
.attr("x", function(d) return d.children ? -8 : 8; )
// 若节点有子节点,那么文字在基点的左上方;否则,在右上方
.style("text-anchor", function(d) return d.children ? "end" : "start"; )
// 节点文字内容的截取方法
.text(function(d) return d.id.substring(d.id.lastIndexOf(".") + 1); );
);
</script>
至此,Cluster Dendrogram图形实现过程解析完毕。下一篇将和Cluster dendrogram非常相似的图,叫Radial Cluster Dendrogram,可以看到,其实就是 Cluster Dendrogram图形的一种变形。
今天是星期六,眼睛酸涩,昨晚没有休息好,希望以后不要再出现这样的情况。
以上是关于D3.js中的Cluster Dendrogram详解的主要内容,如果未能解决你的问题,请参考以下文章
层次聚类python,scipy(dendrogram, linkage,fcluster函数)总算有博文说清楚层次聚类Z矩阵的意义了
R语言ggplot2可视化:为层次聚类树状图dendrogram中的簇进行着色在树状图dendrogram中为不同的层次聚类簇配置不同的色彩