层次结构(Hierarchies)
分析或可视化数据时的一种常用技术是将数据组织成组。(分组)
可以将层次结构视为树状结构,其中根项目(或“节点”)拆分为顶级组。每个顶级组拆分为二级组,依此类推。最顶层的项目(或节点)称为根节点。最底部的项目称为叶子或叶子节点。
有几种方法可以可视化分层数据,包括树、树图、压缩圆图和旭日图。
-
从数据数组创建层次结构:使用 D3 的
.rollup函数按任何分类属性对数据进行分组。第一个参数是要分组的数组;第二个参数是一个reduce函数,这是一个接受值数组并输出单个值的函数;其余参数是指定要分组的属性的函数。可以使用.get检查返回的map对象
function sumWorldwideGross(group) {
return d3.sum(group, function(d) {
return d.Worldwide_Gross;
});
}
let groups = d3.rollup(data,
sumWorldwideGross,
function(d) { return d.Distributor; },
function(d) { return d.Genre; }
);
// Get Sony Pictures
groups.get( Sony Pictures ); // {"Comedy" => 22498520, "Action" => 315268353, "Drama" => 93905424}
// Get Drama within Sony Pictures
groups.get( Sony Pictures ).get( Drama ); // 93905424
-
d3.层次结构:通过调用
d3.hierarchy并传入生成的map对象来创建的d3.rollup
function sumWorldwideGross(group) {
return d3.sum(group, function(d) {
return d.Worldwide_Gross;
});
}
let groups = d3.rollup(data,
sumWorldwideGross,
function(d) { return d.Distributor; },
function(d) { return d.Genre; }
);
let root = d3.hierarchy(groups);
d3.hierarchy输出的是一个嵌套对象,类似于:
{
data: [undefined, Map(3)],
children: [
{
data: ["Sony Pictures", Map(3)],
children: [...],
depth: 1,
height: 1,
parent: {...} // this item s parent node
}.
{
data: ["Walt Disney Pictures", Map(2)],
children: [...],
depth: 1,
height: 1,
parent: {...} // this item s parent node
}.
{
data: ["Warner Bros.", Map(3)],
children: [...],
depth: 1,
height: 1,
parent: {...} // this item s parent node
}
],
depth: 0,
height: 2,
parent: null
}
层次结构中的每个项目(或节点)都有属性:data, children, depth, height and parent.
data是传入的关联项目中的map或对象。一般,不需要访问该值,由于层次结构通过其children和value属性使该数据可用。
children是一个包含节点子节点的数组。
depth和height指示层次结构中节点的深度和高度。
parent引用节点的父节点。
-
可视化层次结构
-
树形布局:第一使用创建树布局函数
d3.tree();可以命令配置树的大小.size;然后,可以调用treeLayout,传入定义的层次结构对象root
var treeLayout = d3.tree(); treeLayout.size([400, 200]); treeLayout(root);这将在
root的每个节点上写入x和y值。绘制节点:
- 用于
root.descendants()获取所有节点的数组 - 将此数组加入圆(或任何其他类型的 SVG 元素)
- 使用
x和y定位圆圈
要绘制链接:
- 用于
root.links()获取所有链接的数组 - 将数组连接到行(或路径)元素
- 使用
x和y链接的source和target属性来定位线
// Nodes d3.select( svg g.nodes ) .selectAll( circle.node ) .data(root.descendants()) .join( circle ) .classed( node , true) .attr( cx , function(d) {return d.x;}) .attr( cy , function(d) {return d.y;}) .attr( r , 4); // Links d3.select( svg g.links ) .selectAll( line.link ) .data(root.links()) .join( line ) .classed( link , true) .attr( x1 , function(d) {return d.source.x;}) .attr( y1 , function(d) {return d.source.y;}) .attr( x2 , function(d) {return d.target.x;}) .attr( y2 , function(d) {return d.target.y;});-
集群布局:与
tree布局超级类似,主要区别在于所有叶节点都放置在一样的深度。
var clusterLayout = d3.cluster() .size([400, 200]); var root = d3.hierarchy(data); clusterLayout(root);-
树状图布局:用于直观地表明每个项目都有关联值的层次结构。
通过调用创建树图布局函数
d3.treemap();可以配置布局;在将此布局应用于层次结构之前,必须在层次结构上运行.sum()。调用treemapLayout,传入root之前定义的层次结构对象.
var treemapLayout = d3.treemap(); treemapLayout .size([400, 200]) .paddingOuter(10); root.sum(function(d) { return d.value; }); treemapLayout(root);树形图布局函数向每个节点添加 4 个属性
x0、x1、y0、y1。它们指定树形图中每个矩形的尺寸。d3.select( svg g ) .selectAll( rect ) .data(root.descendants()) .join( rect ) .attr( x , function(d) { return d.x0; }) .attr( y , function(d) { return d.y0; }) .attr( width , function(d) { return d.x1 - d.x0; }) .attr( height , function(d) { return d.y1 - d.y0; })如果想在每个矩形中添加标签,可以将
g元素加入数组并添加rect和text元素到每个g:var nodes = d3.select( svg g ) .selectAll( g ) .data(rootNode.descendants()) .join( g ) .attr( transform , function(d) {return translate( + [d.x0, d.y0] + ) }) nodes .append( rect ) .attr( width , function(d) { return d.x1 - d.x0; }) .attr( height , function(d) { return d.y1 - d.y0; }) nodes .append( text ) .attr( dx , 4) .attr( dy , 14) .text(function(d) { return d.data.name; })treemap可以通过多种方式配置布局:- 可以使用设置节点子节点周围的填充
.paddingOuter - 兄弟节点之间的填充可以使用
.paddingInner - 可以使用同时设置外部和内部填充
.padding - 外部填充也可以使用,“.paddingTop
、.paddingBottom、.paddingLeft、.paddingRight`进行微调
树形图有不止一种排列矩形的策略。D3 有一些内置的:
treemapBinary,treemapDice,treemapSlice、treemapSliceDice、treemapSquarify- 包布局:类似于树布局,但用圆圈表明节点。
var packLayout = d3.pack(); packLayout.size([300, 300]); rootNode.sum(function(d) { return d.value; }); packLayout(rootNode); d3.select( svg g ) .selectAll( circle ) .data(rootNode.descendants()) .join( circle ) .attr( cx , function(d) { return d.x; }) .attr( cy , function(d) { return d.y; }) .attr( r , function(d) { return d.r; })可以通过
g为每个后代创建元素来添加标签:var nodes = d3.select( svg g ) .selectAll( g ) .data(rootNode.descendants()) .join( g ) .attr( transform , function(d) {return translate( + [d.x, d.y] + ) }) nodes .append( circle ) .attr( r , function(d) { return d.r; }) nodes .append( text ) .attr( dy , 4) .text(function(d) { return d.children === undefined ? d.data.name : ; })可以使用以下方式配置每个圆圈周围的填充
packLayout.padding(10)- 分区布局:将一个矩形空间细分为层,每个层代表层次结构中的一个层。对于层中的每个节点,每一层进一步细分
var partitionLayout = d3.partition(); partitionLayout.size([400, 200]); rootNode.sum(function(d) { return d.value; }); partitionLayout(rootNode); d3.select( svg g ) .selectAll( rect ) .data(rootNode.descendants()) .join( rect ) .attr( x , function(d) { return d.x0; }) .attr( y , function(d) { return d.y0; }) .attr( width , function(d) { return d.x1 - d.x0; }) .attr( height , function(d) { return d.y1 - d.y0; }); partitionLayout.padding(2);如果您想更改分区布局的方向,以便图层从左到右运行,您可以在定义元素时交换
x0、x1和交换:y0、y1.attr( x , function(d) { return d.y0; }) .attr( y , function(d) { return d.x0; }) .attr( width , function(d) { return d.y1 - d.y0; }) .attr( height , function(d) { return d.x1 - d.x0; });还可以将
x尺寸映射到旋转角度和y半径以创建旭日图:var data = { "name": "A1", "children": [ { "name": "B1", "children": [ { "name": "C1", "value": 100 }, { "name": "C2", "value": 300 }, { "name": "C3", "value": 200 } ] }, { "name": "B2", "value": 200 } ] }; var radius = 150; var partitionLayout = d3.partition() .size([2 * Math.PI, radius]); var arcGenerator = d3.arc() .startAngle(function(d) { return d.x0; }) .endAngle(function(d) { return d.x1; }) .innerRadius(function(d) { return d.y0; }) .outerRadius(function(d) { return d.y1; }); var rootNode = d3.hierarchy(data) rootNode.sum(function(d) { return d.value; }); partitionLayout(rootNode); d3.select( svg g ) .selectAll( path ) .data(rootNode.descendants()) .join( path ) .attr( d , arcGenerator); -
树形布局:第一使用创建树布局函数




















暂无评论内容