d3JS v5 specifying domains from nested data for grouped bar charts

邮差的信 提交于 2020-01-06 06:48:44

问题


I am using d3JS v5 (can include lodash as well). I have data which comes as a variable:

 var groupeddata =    [{Title: "Dummy Data", ID: "46", RFU:20291, barcolor: "#ff7f00"},
                       {Title: "Dummy Data", ID: "50", RFU:63, barcolor: "#ff7f00"}, 
                       {Title: "Dummy Data", ID: "56", RFU:6, barcolor: "#ff7f00"},  
                       {Title: "Dummy Data2", ID: "46", RFU:21, barcolor: "#ff7f00"},
                       {Title: "Dummy Data2", ID: "50", RFU:18095, barcolor: "#ff7f00"},
                       {Title: "Dummy Data2", ID: "56", RFU:27278, barcolor: "#ff7f00"}];

Eventually I would like to group the data as per the ID (i.e. have the x axis ticks be the ids), and have bars for each Title as the second layer. The RFU is the height of the bars and the bars be colored as per the barcolor. I was playing around with the nest function to group the data as per IDs. I am not sure if this is required or not but I was able to create a new array as:

var databyID =  d3.nest()
.key(function(d) {  return d.ID;})
.entries(groupeddata);
 console.log(databyID);

Outputs:

       [{key: "46", values:[
           {Title: "Dummy Data", ID: "46", RFU:20291, barcolor: "#ff7f00"},
           {Title: "Dummy Data2", ID: "46", RFU:21, barcolor: "#ff7f00"}] 
        },
       {key: "50", values:[
           {Title: "Dummy Data", ID: "50", RFU:63, barcolor: "#ff7f00"},
           {Title: "Dummy Data2", ID: "50", RFU:18095, barcolor: "#ff7f00"}]
        },
       {key: "56", values:[
               {Title: "Dummy Data", ID: "56", RFU:6, barcolor: "#ff7f00"},
           {Title: "Dummy Data2", ID: "56", RFU:27278, barcolor: "#ff7f00"}]
        }]

I am not able to generate a grouped bar with the code below. It only makes the axis, without the ticks or bars. I believe it is mainly because I am not specifying the correct way to reach to the values in the arrays to specify the x0domain, x1domain and the ydomain. Although I could be completely wrong :). Any help is appreciated. If this question is silly, please forgive me as I am new to D3js and still learning. If more information is needed, please let me know.

Update 1: The RFU data comes as integers and not strings (removed the "").

Thanks.

 var groupeddata =   [{Title: "Dummy Data", ID: "46", RFU:"20291", barcolor: "#ff7f00"},
           {Title: "Dummy Data", ID: "50", RFU:"63", barcolor: "#ff7f00"}, 
           {Title: "Dummy Data", ID: "56", RFU:"6", barcolor: "#ff7f00"},  
           {Title: "Dummy Data2", ID: "46", RFU:"21", barcolor: "#ff7f00"},
           {Title: "Dummy Data2", ID: "50", RFU:"18095", barcolor: "#ff7f00"},
           {Title: "Dummy Data2", ID: "56", RFU:"27278", barcolor: "#ff7f00"}];

  console.log(groupeddata);

  var databyID = d3.nest()
    .key(function(d) {
      return d.ID;
    })
    .entries(groupeddata);
  console.log(databyID);

 divWidth = 700;
  var margin = {top: 30,   right: 100,   bottom: 50,    left: 100,    },
    width = divWidth - margin.left - margin.right,
    height = 250 - margin.top - margin.bottom,

x0 = d3.scaleBand()
.range([0, width - 20], 0.1)
.domain(databyID.map(function(d) {
  d.values.map(function(c) {
    return c.ID;
  }); })),
x1 = d3.scaleBand()
.domain(databyID.map(function(d) {
  d.values.map(function(c) {
    return c.Title;
  }); })),
y = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(databyID, function(d) {
  d.values.map(function(c) {
    return c.RFU;
  }); })]);


  //setup the axis
  var xAxis = d3.axisBottom(x0);
  var yAxis = d3.axisLeft(y);

  var groupedbardiv = d3.select("#groupedBars")
    .append("svg")
    .attr("width", width + margin.left + margin.right - 100)
    .attr("height", height + margin.top + margin.bottom - 10)
    .append("g")
    .attr("transform", "translate (" + margin.left + "," + margin.top + ")");

 //create the x-axis
    groupedbardiv.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate (0, " + height + ")")
      .call(xAxis)
      .selectAll("text")
      .style("text-anchor", "middle")
      .attr("dx", "0em")
      .attr("dy", "-0.55em")
      .attr("y", 30)
      .attr("class", "x-axisticks");
    groupedbardiv.append("text")
      .attr("tranform", "rotate(0)")
      .attr("class", "x axis")
      .attr("x", width)
      .attr("y", height)
      .attr("dy", "0.5em")
      .attr("text-anchor", "end")
      .text("ID")
      .attr("transform", "rotate(0)");

  //create the y-axis
    groupedbardiv.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text")
      .attr("class", "y axis")
      .attr("tranform", "rotate(-90)")
      .attr("y", -10)
      .attr("dy", "0.8em")
      .attr("dx", "3em")
      .attr("text-anchor", "end")
      .text("RFU")
      .attr("transform", "rotate(-90)");

 var bar = groupedbardiv.selectAll("bar")
      .data(databyID)
      .enter()
      .append("rect")
      .style("fill", barcolors)
      .attr("x", function(d) {
        return x0(d.ID);
      })
      .attr("width", x0.bandwidth() - 0.1)
      .attr("y", function(d) {
        return y(d.values.RFU);
      })
      .attr("height", function(d) {
        return height - y(d.values.RFU);
      })
      .attr("fill-opacity", "1.0")
      .attr("class", "y-data");

回答1:


After much searching I found out an example which had data structure similar to mine. I used the following block by Brice Pierre de la Briere

https://bl.ocks.org/bricedev/0d95074b6d83a77dc3ad

Here is my block with the final chart. It also has highlight bars so that even if users put the mouse in empty space above the bars, the bars under it will get highlighted.

https://bl.ocks.org/Coola85/b05339b65a7f9b082ca210d307a3e469



来源:https://stackoverflow.com/questions/50087395/d3js-v5-specifying-domains-from-nested-data-for-grouped-bar-charts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!