Wykres słupkowy D3 działa dobrze, ale nie w przypadku wykresu słupkowego szeregów czasowych.

Po pogrupowaniu według wyniku JSON wynik w konsoli jest poprawny, ale wykres pokazuje dane tylko dla pierwszej znalezionej daty.

var json_data = {
  "headers": ["Month", "Value", "URL", "Number"],
  "rows": [
    ["2018-08-01 00:00:00.0", "One", "www.one.png", 100],
    ["2018-09-01 00:00:00.0", "One", "www.one.png", 300],
    ["2018-10-01 00:00:00.0", "One", "www.one.png", 200],    
    ["2018-11-01 00:00:00.0", "One", "www.one.png", 400],
    ["2018-08-01 00:00:00.0", "Two", "www.two.png", 100],
    ["2018-09-01 00:00:00.0", "Two", "www.two.png", 224],    
    ["2018-10-01 00:00:00.0", "Two", "www.two.png", 259],
    ["2018-11-01 00:00:00.0", "Two", "www.two.png", 494],
    ["2018-08-01 00:00:00.0", "Three", "www.three.png", 100],
    ["2018-09-01 00:00:00.0", "Three", "www.three.png", 184],    
    ["2018-10-01 00:00:00.0", "Three", "www.three.png", 319],
    ["2018-11-01 00:00:00.0", "Three", "www.three.png", 404],
    ["2018-08-01 00:00:00.0", "Four", "www.four.png", 100],
    ["2018-09-01 00:00:00.0", "Four", "www.four.png", 184],
    ["2018-11-01 00:00:00.0", "Four", "www.four.png", 404],
    ["2018-08-01 00:00:00.0", "Five", "www.five.png", 100],
    ["2018-09-01 00:00:00.0", "Five", "www.five.png", 274],    
    ["2018-10-01 00:00:00.0", "Five", "www.five.png", 209],
    ["2018-11-01 00:00:00.0", "Five", "www.five.png", 474]
  ]
};

var dataRows = json_data.rows;


/* ----- !Data ----- */

/* ----- Functions ----- */

//Group by function. Provide the rows to be groupped and the number of objects to be used as a key.
groupBy = (rows, objectNum) => {
    const 
      rowMap = new Map(),
      result = [],
      dataTemp = [];
      
    // Iterate over the rows.
    rows.forEach(row => {
      const
        // Create a key, it is the first elements joined together.
        key = row.slice(0,objectNum).join();
        
      // Check if the Map has the generated key...
      if (rowMap.has(key)) {
        // The map has the key, we need to add up the values
        // Get the value for the current key.
        const storedRow = rowMap.get(key);
        // Add the value of the current row to the row in the map.
        storedRow[3] += row[3];
      } else {
        // The key doens't exist yet, add the row to the map. Clone the array instead of "rowMap.set(key, row);"
        rowMap.set(key, row.slice());
      }
    });
    // Iterate over all the entries in the map and push each value with the summed up value into the array.
    rowMap.forEach(value => {
      result.push(value);
    });
    
      return result;
  }

//Chart creation function
createChart = (data) =>{
	var svg = d3.select(".g-chart").append("svg"),
    margin = { top: 20, right: 20, bottom: 30, left: 40 },
    x = d3.scaleBand().padding(0.1),
    y = d3.scaleLinear(),
    theData = undefined;

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

  g.append("g")
    .attr("class", "axis axis--x");

  g.append("g")
    .attr("class", "axis axis--y");

  g.append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.71em")
    .attr("text-anchor", "end")
    .text("num");

  // DRAWING
  function draw() {

    var bounds = svg.node().getBoundingClientRect(),
      width = bounds.width - margin.left - margin.right,
      height = bounds.height - margin.top - margin.bottom;

    x.rangeRound([0, width]);
    y.rangeRound([height, 0]);

    g.select(".axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    g.select(".axis--y")
      .call(d3.axisLeft(y).ticks(10));

    var bars = g.selectAll(".bar")
      .data(theData);

    // ENTER
    bars
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function (d) { return x(d.Value); })
      .attr("y", function (d) { return y(d.num); })
      .attr("width", x.bandwidth())
      .attr("height", function (d) { return height - y(d.num); });

    // UPDATE
    bars.attr("x", function (d) { return x(d.Value); })
      .attr("y", function (d) { return y(d.num); })
      .attr("width", x.bandwidth())
      .attr("height", function (d) { return height - y(d.num); });

    // EXIT
    bars.exit()
      .remove();

  }

  // LOADING DATA
  function loadData(data) {

      theData = data;

      x.domain(theData.map(function (d) { return d.date; }));
      y.domain([0, d3.max(theData, function (d) { return d.num; })]);

      draw();

  }

  // START!
  
  window.addEventListener("resize", draw);
  loadData(data);
}

//Create dictionary function (transformed JSON)
createDict = (data, objectNum) => {

  groupedData = groupBy(dataRows, objectNum);
  var dict = [];
  for (i = 0; i < groupedData.length; i++) {
    var object = {
      "date": groupedData[i][0].slice(0, 10),
      "Value": "Total",
      "num": groupedData[i][3]
    };
    dict.push(object);
  }

  return dict;

}


/* ----- !Functions ----- */

/* ----- Main ----- */

var initialdata = createDict(dataRows, 1);
console.log(JSON.stringify(initialdata));

createChart(initialdata);

/* ----- !Main ----- */
@import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;font-size:18px;overflow:hidden;color:#555}svg{width:100%;height:200px}.bar{fill:#124}.bar:hover{fill:#565656}.axis--x path{display:none}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div class="g-chart"></div>
0
Datacrawler 7 listopad 2018, 18:19

1 odpowiedź

Najlepsza odpowiedź

Problem wydaje się polegać na tym, że podczas określania dziedziny skali x za pomocą d.date, ustawiasz atrybut x słupków za pomocą d.Value . Ponieważ d.Value wydaje się być na stałe zakodowane na „Total”, prawdopodobnie chcesz zmienić wiersze attr("x" na coś takiego

.attr("x", function (d) { return x(d.date); // was d.Value })

0
maggiomj 7 listopad 2018, 20:38