1

我第一次深入研究 D3,并试图创建一个小的条形图,以可视化一些关于食品消费随时间推移的研究。使用一些在线示例,我设法让面积图正常工作。但是条形图会让我更好地理解数据。我觉得到目前为止我的代码已经接近工作,但我显然错过了一些东西。任何提示或帮助都会很棒。

例如,这是我的 .csv 文件的片段:

group,date,totals
acid,1641,8438
bird,1641,12
cheese,1641,22
cured meat,1641,506
dried fish,1644,158
fresh fish,1644,1196
meat,1644,140
brined/pickled fish,1645,2844
salt,1645,4382
...

到目前为止的代码:

<script type="text/javascript">

var margin = {top: 20, right: 30, bottom: 30, left: 40},
    width = 500 - 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([height, 0]);

// for the area charts example, an area generator
var area = d3.svg.area()
    .interpolate("monotone")
    .x(function(d) { return x(d.date); })
    .y0(height)
    .y1(function(d) { return y(d.totals); });

// for the area charts example, a line generator
var line = d3.svg.line()
    .interpolate("monotone")
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.totals); });

// 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)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

    // Trying here to render my bar charts. 
    // -----------------------------------
    svg.selectAll(".bar")
       .data(groups)
     .enter().append("rect")
       .attr("x", x)
       .attr("y", function(d) { return d.maxtotals; })
       .attr("width", width / groups.length)
       .attr("height", function(d) { return d.maxtotals; });

// These are the area charts, that work. Commented out for now.
  //svg.append("path")
  //    .attr("class", "area")
  //    .attr("d", function(d) { y.domain([0, d.maxtotals]); return area(d.values); });

  //svg.append("path")
  //    .attr("class", "bar")
  //    .attr("d", function(d) { y.domain([0, d.maxtotals]); return line(d.values); });


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

</script>

面积图现在看起来像这样(上面的代码改变了它们的外观,但它给了你一个想法):

屏幕抓取

任何指针?我在看什么?提前谢谢!

4

2 回答 2

1

我突然想到的第一件事是你没有在你的和属性中应用你的y比例,也没有适当地缩放属性。由于您确定这些属性值的方式,它应该像将比例应用于您已经返回的值一样简单。请注意,在未来,这可能无法正常工作。d.maxtotals"y""height""width"

另一个问题是,您可能根本不打算让"y"属性与您的数据相关。那"height"是工作。将它们"y"属性设置为您提供给 x 轴的相同 y 坐标。

于 2013-03-28T18:41:55.047 回答
1

感谢Elijah的一些惊人帮助,我们成功地完成了这项工作。这是修订版:

<script type="text/javascript">

var margin = {top: 20, right: 30, bottom: 30, left: 40},
    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]);

// 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)
      .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; })]);

  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.year())})
    // .attr("class", "bar")
    })

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

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

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

});

</script>

主要变化:.each()函数作为g元素添加到SVG中,data.values作为其数据调用。y()比例也被翻转(从到0,hh,0。我的另一个疏忽是该.each()功能已包含该d3.max()功能,因此每个项目组的最大总数是针对单个组而不是所有组进行检查的。现在,我已经很好地呈现了条形图,而不是面积图,它显示了每个食物组的总量。

于 2013-04-01T04:23:12.980 回答