d3js条形图:两个条形可以代表两个不同的类别/变量吗?

时间:2014-03-28 16:05:13

标签: javascript d3.js bar-chart

我的数据看起来像这样:

var data = {

     { name: Andrew,
       date: 12/08/07,
       alpha: 1.2,
       beta: 3.4
     },
     { name: Fred,
       date: 14/12/06,
       alpha: 1.7,
       beta: 2.8
     }
};

我想要一个在x轴上带有名字的条形图,每个名字都有两个条形:一个用于alpha,一个用于beta。我遇到的所有示例都将类别/格式中的条形图分组(例如,所有条形代表日期等),这就是为什么他们的解决方案没有多大帮助。我到目前为止:

var x0 = d3.scale.ordinal()
            .rangeRoundBands([0, width], 0.2);

    var x1 = d3.scale.ordinal();

    var y = d3.scale.linear()
         .range([height, 0]);

    var color = d3.scale.ordinal()
            .range([ "#6b486b", "#ff8c00"]);

    var xAxis = d3.svg.axis()
            .scale(x0)
            .orient("bottom");

    var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left")
            .tickFormat(d3.format(".2s"));

    var svg = d3.select("#punchcard").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 + ")");

    var ageNames = ["Alpha", "Beta"];

    x0.domain(patient_names);
    x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()], 0);
    console.log(patientList);


    console.log(data);

    var alpha_max = d3.max(data, function(d) {return parseFloat(d.alpha); });
    var beta_max = d3.max(data, function(d) { return parseFloat(d.beta); });

    console.log(alpha_max);
    console.log(beta_max);
    var y_domain = [ alpha_max, beta_max];

    y.domain([0, parseFloat(d3.max(y_domain))+0.5]);

    svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

    svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end");

    svg.selectAll("bars")
        .data(data)
        .enter().append("rect")
        .attr("transform", function(d) { return "translate(" + x0(d.name)+",0)";})
        .style("fill", "#ff8c00")
        .attr("x", function(d) { return x1(d.alpha); })
        .attr("width", x1.rangeBand())      
        .attr("y", function(d) { return y(d.alpha); })
        .attr("height", function(d) { return height - y(d.alpha); });

    svg.selectAll("bars")
        .data(data)
        .enter().append("rect")
        .style("fill", "#6b486b")
        .attr("transform", function(d) { return "translate(" + x0(d.name)+",0)";})
        .attr("x", function(d) { return x1(d.beta); })
        .attr("width", x1.rangeBand())      
        .attr("y", function(d) { return y(d.beta); })
        .attr("height", function(d) { return height - y(d.beta); });


var legend = svg.selectAll(".legend")
      .data(ageNames.slice().reverse())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });

此代码堆叠alpha和beta条而不是彼此。我花了几个小时看各种例子,但仍然无法找到一种方法。

提前致谢!

1 个答案:

答案 0 :(得分:1)

您可以使用第二个数据连接中的映射函数创建嵌套数组数据结构,每个变量有一个对象。

首先将组加入数据对象数组,然后使用嵌套数据连接中的函数为每个组动态创建子数组:

var propertyNames = ["Alpha", "Beta"];

var groups = plottingArea.selectAll("g.groups")
                .data(data);

/* and handle the enter selection, classes, etc */

var bars = groups.selectAll("rect.bars")
                .data( function(d) {
                   //the `d` value is the data object for the *group*
                   //this function needs to return an array of data objects
                   //representing each bar in the group

                   return propertyNames.map( function(property){
                      //to get one bar for each variable, start with the
                      //array of variable names, and use a map function
                      //to create data objects for each:

                      return { type: property,
                               value: d[property],
                               name: d.name,
                               date: d.date
                             };

                   });

                });

其余代码应遵循标准grouped bar chart结构。您创建的内部数据对象应包含正确定位和着色每个条形所需的所有数据。