d3.js堆叠条形图-修改堆叠顺序逻辑 [英] d3.js stacked bar chart - modify stack order logic

查看:95
本文介绍了d3.js堆叠条形图-修改堆叠顺序逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个堆叠的条形图,其中rects的顺序由数据值(即,最大到最小,最高到最短,最丰富到最穷等)确定.据我所知,在堆叠数据后,似乎保留了 initial 顺序.这可以在我的代码段中看到,硬编码的数据使我们可以看到 d3.stack()之前和之后的情况.请注意,第三个矩形 fmc3 t1 中的第三大矩形变为 t3 中所有矩形中的最大矩形,尽管它在堆栈中的位置仍然保留一样:

I would like to create a stacked bar chart whereby the order of the rects is determined by data values (i.e. largest to smallest, tallest to shortest, richest to poorest, ect). To the best of my knowledge, after stacking data, the initial order seems to be preserved. This can be seen in my snippet, hardcoded data lets us see what's happening before and after d3.stack(). Note that the third rect fmc3 goes from being the third largest in t1 to the largest of all rects in t3 despite its position in the stack remaining the same:

var margins = {top:100, bottom:300, left:100, right:100};

var height = 600;
var width = 900;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);

var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");


  var data = [
{period:'t1', fmc1:2, fmc2:5, fmc3:6, fmc4:9, fmc5:10},
{period:'t2', fmc1:3, fmc2:4, fmc3:9, fmc4:8, fmc5:11},
{period:'t3', fmc1:3, fmc2:5, fmc3:15, fmc4:12, fmc5:10},
  ];

  var groups = d3.map(data, function(d){return(d.period)}).keys();

var subgroups = Object.keys(data[0]).slice(1);

  var stackedData = d3.stack()
   .keys(subgroups)
   (data);

//console.log(stackedData);

  var yScale = d3.scaleLinear()
  .domain([0,80])
  .range([height,0]);

  var xScale = d3.scaleBand()
  .domain(['t1','t2','t3'])
  .range([0,width])
  .padding([.5]);

  var colorScale = d3.scaleOrdinal()
  .domain(subgroups)
  .range(["#003366","#366092","#4f81b9","#95b3d7","#b8cce4","#e7eef8","#a6a6a6","#d9d9d9","#ffffcc","#f6d18b","#e4a733","#b29866","#a6a6a6","#d9d9d9","#e7eef8","#b8cce4","#95b3d7","#4f81b9","#366092","#003366"].reverse());

  graphGroup.append("g")
  .selectAll("g")
  .data(stackedData)
  .enter().append("g")
.attr("fill", function(d) { return colorScale(d.key); })
.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
  .attr("x", function(d) { return xScale(d.data.period); })
  .attr("y", function(d) { return yScale(d[1]); })
  .attr("height", function(d) { return yScale(d[0]) - yScale(d[1]); })
  .attr("width",xScale.bandwidth());

<script src="https://d3js.org/d3.v5.min.js"></script>

我怀疑保留初始顺序在某种程度上可能有必要计算堆栈中的相邻矩形.但是,另一方面,在可视化之前对数据进行排序是可视化领域中非常普遍的做法,甚至是首选做法,如果没有人找到解决这个问题的方法,我会感到惊讶.

I suspect preserving the initial order may be somewhat necessary to calculate adjacent rects in the stack. However, on the other hand, ordering data before visualizing it is a very common, even preferred practice in the field of visualization and I would be surprised if no one has found a solution to this issue yet.

鉴于没有内置功能来指定堆栈中rect的顺序,我应该如何使用排序逻辑来实现从大到小的排序?

Given there are no built-in features to specify the ordering of the rects in a stack, how should I approach the sort logic to achieve largest to smallest ordering?

推荐答案

好吧,一个内置功能,用于指定顺序,即

Well, there is a built-in feature to specify the order, which is stack.order(). However, it specifies the order computing the entire series, not every single value the stack (which I believe is what you want... in that case, you'll have to create your own function).

例如,使用 stack.order(d3.stackOrderDescending):

var margins = {
  top: 0,
  bottom: 0,
  left: 0,
  right: 0
};

var height = 300;
var width = 500;

var totalWidth = width + margins.left + margins.right;
var totalHeight = height + margins.top + margins.bottom;

var svg = d3.select('body')
  .append('svg')
  .attr('width', totalWidth)
  .attr('height', totalHeight);

var graphGroup = svg.append('g')
  .attr('transform', "translate(" + margins.left + "," + margins.top + ")");


var data = [{
    period: 't1',
    fmc1: 2,
    fmc2: 5,
    fmc3: 6,
    fmc4: 9,
    fmc5: 10
  },
  {
    period: 't2',
    fmc1: 3,
    fmc2: 4,
    fmc3: 9,
    fmc4: 8,
    fmc5: 11
  },
  {
    period: 't3',
    fmc1: 3,
    fmc2: 5,
    fmc3: 15,
    fmc4: 12,
    fmc5: 10
  },
];

var groups = d3.map(data, function(d) {
  return (d.period)
}).keys();

var subgroups = Object.keys(data[0]).slice(1);

var stackedData = d3.stack()
  .keys(subgroups)
  .order(d3.stackOrderDescending)
  (data);

//console.log(stackedData);

var yScale = d3.scaleLinear()
  .domain([0, 60])
  .range([height, 0]);

var xScale = d3.scaleBand()
  .domain(['t1', 't2', 't3'])
  .range([0, width])
  .padding([.5]);

var colorScale = d3.scaleOrdinal()
  .domain(subgroups)
  .range(["#003366", "#366092", "#4f81b9", "#95b3d7", "#b8cce4", "#e7eef8", "#a6a6a6", "#d9d9d9", "#ffffcc", "#f6d18b", "#e4a733", "#b29866", "#a6a6a6", "#d9d9d9", "#e7eef8", "#b8cce4", "#95b3d7", "#4f81b9", "#366092", "#003366"].reverse());

graphGroup.append("g")
  .selectAll("g")
  .data(stackedData)
  .enter().append("g")
  .attr("fill", function(d) {
    return colorScale(d.key);
  })
  .selectAll("rect")
  .data(function(d) {
    return d;
  })
  .enter().append("rect")
  .attr("x", function(d) {
    return xScale(d.data.period);
  })
  .attr("y", function(d) {
    return yScale(d[1]);
  })
  .attr("height", function(d) {
    return yScale(d[0]) - yScale(d[1]);
  })
  .attr("width", xScale.bandwidth());

<script src="https://d3js.org/d3.v5.min.js"></script>

这篇关于d3.js堆叠条形图-修改堆叠顺序逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆