【问题标题】:Am I mapping or nesting this data incorrectly?我是否错误地映射或嵌套了这些数据?
【发布时间】:2013-04-15 21:25:06
【问题描述】:

我正在寻找一些关于如何解决如何将我的数据可视化为条形图的指示。我创建了一个随时间出现的数据的小倍数可视化。由于数据收集方式的性质,数据具有某些属性。例如,您可以看到下面的 .csv 摘录,其中重复了 groupdate

group,date,totals
acid,1641,8438
acid,1641,0
acid,1641,0
beef,1641,977.85
beef,1641,0
beef,1641,0
beef,1641,164
beef,1641,5.25
bird,1641,121
bird,1641,0
bird,1641,12
bird,1641,1558
bird,1641,729
bird,1641,1680
bird,1641,0
bird,1641,343
bird,1641,3
bird,1641,2092
bird,1641,0
bird,1641,0
bird,1641,107
bird,1641,2679
bird,1641,167
bird,1641,649
boar,1641,41
boar,1641,13
cheese,1641,13
cheese,1641,22
cheese,1641,1071
cheese,1641,17195

(可以看到entire dataset here。)

我遇到的问题是共享date 的任何地方,而不是将totals 列相加,而是将数据堆叠在一起。例如,参见:

我正在努力将数据显示为单个条形图。 (我有一个 y 轴无法正确缩放的次要问题)。我尝试使用nest 来解决多年来的问题(这适用于groups),但我似乎无法使用date

到目前为止,这是我的代码:

var margin = {top: 20, right: 30, bottom: 30, left: 50},
    width = 400 - margin.right - margin.left,
    height = 150 - margin.top - margin.bottom,
    parse = d3.time.format("%Y").parse;

// scales
var x = d3.time.scale().range([0, width]),
    y = d3.scale.linear().range([0, height]),
    yscaled = d3.scale.linear().range([height, 0]);

// load data
d3.csv("revised.csv", function(error, data) {

  // nest values by group
  var groups = d3.nest()
      .key(function(d) { return d.group; })
      .entries(data);

  // parse dates and numbers, assume values are sorted by date
  // compute the maximum totals per group
  groups.forEach(function(s) {
    s.values.forEach(function(d) { d.date = parse(d.date); d.totals = +d.totals; });
    s.maxtotals = d3.max(s.values, function(d) { return d.totals; });
  });

  // compute the minimum and maximum date across groups
  x.domain([
    d3.min(groups, function(s) { return s.values[0].date; }),
    d3.max(groups, function(s) { return s.values[s.values.length - 1].date; })
  ]);
  // y.domain([0, d3.max(data, function(d) { return d.totals; })]);

  // add an SVG element for each group
  var svg = d3.select("body").selectAll("g")
      .data(groups)
    .enter().append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

  var canvas_g = svg.append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .each(function(d) {
          var g = d3.select(this);
          g.append("g");
        // .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        y.domain([0, d3.max(d.values, function(r) { return r.totals; })]);
        yscaled.domain([0, d3.max(d.values, function(r) { return r.totals; })]);

      // Draw the charts.

        g.selectAll("rect.aevents")
          .data(d.values)
        .enter().append("rect")
          .attr("height", function(p) {return y(p.totals)})
          .attr("width", 5)
          .attr("x", function(p, q) {return x(p.date)})
          .attr("y", function(p) {return height - y(p.totals)})
          // .on("click", function(p) {console.log(p.date)})
          .attr("class", "bar");
      });

  // draw x axis
  canvas_g.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.svg.axis().scale(x).orient("bottom"));

  // draw y axis
  canvas_g.append("g")
      .attr("class", "y axis")
      .call(d3.svg.axis().scale(yscaled).orient("left"));

  // add a small label for the group name
  svg.append("text")
      .attr("x", width + 40)
      .attr("y", height + 15)
      .attr("text-anchor", "end")
      .text(function(d) { return d.key; });

});

我应该以不同的方式循环数据吗?或者,我是否需要以某种方式重组数据?提前谢谢!

【问题讨论】:

  • 当它们在日期发生碰撞时,你想如何表示它们?您是否希望它们具有相同的大小并向右移动,有可能会检查未来的日期数据,或者您是否想做其他事情?这种可视化的问题在于,您将 x 坐标用作与时间不同的比例。这种用法可能会有更好的可视化效果。
  • 如果数据在某个日期发生冲突,我希望将数据汇总在一起。因此,在上面的 beef 示例中,而不是在 1641 年三个条相互堆叠,而是返回 1147.1
  • 你能设置一个jsfiddle吗?这会让事情变得更容易......

标签: d3.js


【解决方案1】:

首先,您可以阅读this 的答案,如果您想了解更多有关d3.nest() 的信息,这将对您有所帮助。

对于您的问题,一个好的方法是首先使用d3.nest() 嵌套元素,然后将组映射到所需的形式。这给出了:

function formatData(inputData){ 
    var array = d3.nest()
        .key(function(d){return d.group})
        .key(function(d){return d.date})
        .entries(inputData)
        .map(function(d){
            var group = d.key
            var values = d.values.map(function(dd){
                var date = dd.key
                var total = 0
                dd.values.forEach(function(ddd){
                    total = total + ddd.totals        
                })
                return {date:date, totals:total}
            })
            return {'group':group, 'values':values}
        })
    obj = {}
    array.forEach(function(d){
        obj[d.group] = d.values
    })
    return obj
}

inputData 是使用 d3.csv() 加载的数据。这样你就可以充分利用 nest() 和 `map()`

如果您只想为牛肉绘制条形图,您现在可以这样做:

var beefData = formatData(myInput).beef

jsFiddle:http://jsfiddle.net/chrisJamesC/FJmMD/3/

【讨论】:

  • 感谢您的建议!我想我越来越近了,但我收到了奇怪的数据。它或多或少是准确的,但我在totals 前附加了零,如下所示:{"acid":[{"date":"1641","totals":"0843800"},{"日期":"1644","总计":"0435200"},{"日期":"1645","总计":"0551800"},{"日期":"1648","总计":"0700" },{"date":"1656","totals":"0000"},{"date":"1657","totals":"0000"},{"date":"1659","totals" :"04800"},{"date":"1662","totals":"0000"},{"date":"1663","totals":"01205300"},{"date":"1664" ,"totals":"0192000"},{"date":"1665","totals":"0000"}
  • 我访问 CSV 的方式有问题吗?当我使用您的示例数据集运行所有内容时,它似乎工作正常:jsfiddle.net/hepplerj/7jgqW.
  • 问题是您没有将字符串转换为整数。只需将我计算总数的行替换为:total = total + parseFloat(ddd.totals)。这里是对应的jsFiddle
猜你喜欢
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
相关资源
最近更新 更多