d3. js Диаграмма с накоплением - не отображается - PullRequest
1 голос
/ 20 февраля 2020

Я строю сложенный граф областей (после этого урока ) и у меня проблемы с рендерингом графика. Оси отображаются правильно, но элементы области не отображаются. При использовании только одного столбца данных он работает нормально, но после суммирования данных не повезло.

Я чувствую, что проблема связана с моим использованием scaleLinear().

У меня есть попробовал два метода: помещая y значения из функции d3.stack, я получаю отрицательные значения (прокомментировано в коде ниже). Во-вторых, для отладки я установил максимум на максимум stackedData (по умолчанию в коде ниже). Это дает все положительные значения, когда я использую console.log, но граф не визуализируется.

Вот код:

var margin = {top: 10, right: 30, bottom: 30, left: 70},
  width = 460 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

var svg = d3.select("#chart")
  .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+")");
let data = []
var group_names = []
//Assumes first line of data is table header, otherwise will not work properly
model.output_energy_demand.map(function(x,i){
  if(i==0) {
    group_names = x
  }else{
    let line = {}
    x.map(function(y,j){
      line[group_names[j]]=y
    });
    data.push(line)
  }
});

data.forEach((d,i)=>{
    var keys = Object.keys(d)
    console.log(model.year[i])
    d["year"] = d3.timeParse("%Y")(model.year[i])
    for(var j=0;j<keys.length;j++){
      d[keys[i]] = +d[keys[j]]
    }
  });
if(typeof(data)!="undefined") {
  console.log("Data loaded")
  console.log(model.year)

  //Stacking data
  var sumstat = d3.nest()
    .key(function(d) { return d.year;})
    .entries(data);

  var stackedData = d3.stack()
  .keys(group_names)
  .value(function(d,key){
    return d.values[0][key]
  })(sumstat);

  //Set up axes
  var x = d3.scaleTime()
    .domain(d3.extent(model.year.map((d,i)=>{return d3.timeParse("%Y")(d)})))
    .range([0,width]);
  svg.append("g")
    .attr("transform","translate(0,"+height+")")
    .call(d3.axisBottom(x));
  svg.append("text")
    .attr("x",width*.5)
    .attr("y",height+margin.bottom)
    .style("text-anchor","middle")
    .attr("font-family","Tahoma")
    .text("Year")

  var y = d3.scaleLinear()
  // Finds maximum of stackedData, which avoids negative values (but gives incorrect values on the y-axis) 
  .domain([0,d3.max(stackedData,
    function(d){
      //Find maximum value of data
      var max = 0;
      d.forEach(function(e,i){
        console.log(e);
        if(d3.max(e)>max) max=d3.max(e)
    })
    return max
    })
  ])
 // Finds maximum of stackedData, which gives correct values on the y-axis, but causes negative values to come out of y(d[0])
// .domain([0,d3.max(data,
  //   function(d){
  //     //Find maximum value of data
  //     var max = 0;
  //     group_names.forEach(function(key,i){
  //       console.log(key);
  //       if(d[key]>max) max=d[key]
  //   })
  //   return max
  //   })
  // ])
  .range([ height,0])

  svg.append("g")
  .call(d3.axisLeft(y));

  svg.append("text")
    .attr("y",-margin.left)
    .attr("x",-height*.5)
    .attr("dy","1em")
    .style("text-anchor","middle")
    .attr("font-family","Tahoma")
    .attr("transform","rotate(-90)")
    .text("Energy Demand (TWh /year)")

  console.log("About to plot data ")
  svg
    .selectAll("layers")
    .data(stackedData)
    .enter()
    .append("path")
      .attr("fill",function(d){return color()})
      .attr("d", d3.area()
        .x(function(d,i){ console.log("Data on line", d.data); return x(d3.timeParse("%Y")(d.data.key)) })
        .y0(function(d) {console.log(d[0] +"-> y0: "+y(d[0])); return y(d[0])})
        .y1(function(d){ console.log(d[1] + "-> y1: "+y(d[1])); return y(d[1])})
        )
}else{
  d3.select("#chart").append("Error loading data")
}

Вот структура data:

enter image description here

(33) […]
​
0: {…}
​​
"Electricity by CSP": 0
​​
"Electricity by PV": 0
​​
"Electricity by geothermal": 0
​​
"Electricity by hydropower": 300.89983280022
​​
"Electricity by marine power": 0
​​
"Electricity by offshore wind": 0
​​
"Electricity by onshore wind": 0
​​
"Renewable energy": 258.219863514757
​​
"Solid bioenergy": 254.640155086192
​​
"Total demand for coal": 3711.42425220673
​​
"Total demand for crude oil": 7523.960117178
​​
"Total demand for natural gas": 254.640155086192
​​
"Total demand for nuclear fuel": 2449.95477156234
​​
year: Date Mon Jan 01 1990 00:00:00 GMT+0000 (Greenwich Mean Time)
​​
<prototype>: Object { … }
​
1: Object { "Total demand for natural gas": 3220.14298481777, "Total demand for crude oil": 277.599399485849, "Total demand for coal": 3662.11547993736, … }
​
2: Object { "Total demand for natural gas": 3200.81379949803, "Total demand for crude oil": 7756.9933670896, "Total demand for coal": 273.508068071529, … }

...

Есть идеи?

РЕДАКТИРОВАТЬ: 2020-02-21 Я разместил живую версию здесь: https://jsfiddle.net/turium/ywrbkzm9/

1 Ответ

1 голос
/ 21 февраля 2020

Я проверил ваш код, и было несколько ошибок. Я заменил их на правильные, вы можете выполнить ваши исследования и разработки.

  • Функция вызова цвета не вызывается из того места, где вы добавляете путь.
  • там было ненужное вложение данных.
  • создал пустой объект модели, поэтому jsfiddle выдавал ошибку
  • удалил шкалу времени при добавлении служебной информации

Код для отображения оси x с годы без запятых.

svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(function(d) {
  return d;
}));

model = {}
model.year = [
  1990,
  1991,
  1992,
  1993,
  1994,
  1995,
  1996,
  1997,
  1998,
  1999,
  2000,
  2001,
  2002,
  2003,
  2004,
  2005,
  2006,
  2007,
  2008,
  2009,
  2010,
  2011,
  2012,
  2013,
  2014,
  2015,
  2020,
  2025,
  2030,
  2035,
  2040,
  2045,
  2050
]
model.output_energy_demand = [
  [
"Total demand for natural gas",
"Total demand for crude oil",
"Total demand for coal",
"Electricity by geothermal",
"Electricity by hydropower",
"Electricity by marine power",
"Electricity by CSP",
"Electricity by PV",
"Electricity by offshore wind",
"Electricity by onshore wind",
"Total demand for nuclear fuel",
"Renewable energy",
"Solid bioenergy"
  ],
  [
3102.40524991691,
7523.960117178,
3711.42425220673,
0,
300.89983280022,
0,
0,
0,
0,
0,
2449.95477156234,
258.219863514757,
254.640155086192
  ],
  [
3220.14298481777,
7805.34286934201,
3662.11547993736,
0,
314.08215981732,
0,
0,
0,
0,
0,
2392.85347025885,
281.174663414415,
277.599399485849
  ],
  [
3200.81379949803,
7756.9933670896,
3445.10585509343,
0,
340.4890868346,
0,
0,
0,
0,
0,
2512.86260946551,
277.266526000094,
273.508068071529
  ],
  [
3305.31292778359,
7783.82326263428,
3472.68950574908,
0,
353.62925132022,
0,
0,
0,
0,
0,
2666.91820506714,
305.773519651316,
302.045477722751
  ],
  [
3367.00236478057,
7565.09225038114,
3413.93067723008,
0,
367.522212360599,
0,
0,
0,
0,
0,
2657.48508853596,
292.303360572476,
288.50963564391
  ],
  [
3487.48732706185,
7615.43451245472,
3406.94135763491,
0,
362.74326344874,
0,
0,
0,
0,
0,
2720.41544041992,
297.511985344959,
293.709384916393
  ],
  [
3744.9593399799,
7826.17851688842,
3449.136453147,
0,
355.3673026203,
0,
0,
0,
0,
0,
2871.17913811302,
323.48891655571,
319.711924627145
  ],
  [
3734.32219482531,
7545.58234604822,
3285.22078771847,
0,
367.27291222956,
0,
0,
0,
0,
0,
2895.07611993084,
333.778821035599,
329.987640607034
  ],
  [
3834.40132308377,
7645.80240057448,
3258.37777947803,
0,
377.0867016027,
0,
0,
0,
0,
0,
2889.95225758379,
334.216219338001,
330.408223409436
  ],
  [
3934.10235529276,
7393.72102051037,
3147.43143379234,
0,
383.18690200752,
0,
0,
0,
0,
0,
2914.35741090846,
327.381123667362,
323.534358238797
  ],
  [
4087.04502061623,
7247.4110570115,
3353.99479917852,
4.82547708666,
393.52232123964,
0.5071937472,
0,
0.203524605,
0,
26.81745703056,
2931.59347644636,
332.014849186351,
326.489968757786
  ],
  [
4187.85080191466,
7646.26147968543,
3384.51199334096,
4.64857517429999,
420.262811562959,
0.4852086192,
0,
0.30943918638,
0,
33.45917086152,
3022.71240680316,
336.487547234091,
330.881864107789
  ],
  [
4205.18925700953,
7579.67080593577,
3385.97805263338,
4.79569679315999,
353.99917660788,
0.494507592,
0,
0.4051566306,
0,
46.3006537083,
3067.10289195713,
337.738844971462,
332.131957416555
  ],
  [
4428.70123473367,
7834.71813308874,
3524.45624865725,
5.4612635832,
343.52520531084,
0.4898581056,
0,
0.72565105788,
0,
50.9478361405199,
3069.27182555567,
374.37075694017,
368.147127662413
  ],
  [
4551.82743034029,
8009.62808231553,
3449.96219341097,
5.564770758,
362.514048853499,
0.470082009599999,
0,
1.46273236614,
0,
67.69761449058,
3119.33911585662,
366.098265091526,
359.153478032005
  ],
  [
4604.74358239693,
8096.18416223813,
3381.05306785008,
5.44094040114,
344.3848462566,
0.4813375536,
0,
2.64236395716,
0,
78.3154704733199,
3066.35144843448,
386.969328558568,
379.391483494566
  ],
  [
4560.10999341729,
8203.04705336058,
3469.86003803626,
5.61711543678,
346.81026188232,
0.4642543728,
0,
3.73148887734,
0,
91.38316529736,
3050.45111617217,
394.148276719482,
385.458486662152
  ],
  [
4519.7188056018,
7948.7483718475,
3463.98671155763,
5.82834632004,
349.48220898564,
0.4654325232,
0.00484251372,
6.14455873164,
0,
118.81064914452,
2896.72897237308,
411.77345085889,
401.790597859782
  ],
  [
4642.45980752563,
8095.41788904162,
3208.68777524172,
5.78038393997999,
368.10858903516,
0.4654325232,
0.0094111776,
12.7615925908799,
2.60895690648,
132.13721227626,
2918.12383597752,
446.017117805582,
433.655553095456
  ],
  [
4300.19124830045,
7719.81278137145,
2876.38739207936,
5.58780088086,
371.310269112539,
0.44894025846,
0.11373727212,
20.3917959088199,
5.744841114762,
145.29539623914,
2921.42403037908,
467.905545984921,
453.394070650256
  ],
  [
4692.03986900568,
7797.53751476991,
2959.25747160129,
5.6382101145,
412.797954991499,
0.477972636839999,
0.8062598628,
35.0866669474799,
8.22484405134,
157.81866688674,
2856.24810989478,
498.364549610955,
481.466736916603
  ],
  [
4235.58374324098,
7538.66495957225,
3005.00134812211,
5.91160946975999,
344.426769476279,
0.478098341279999,
1.3839112116,
66.1100621738399,
11.72086686054,
179.46124283664,
2799.25195982939,
442.390139292031,
425.641578089282
  ],
  [
4107.70809841702,
7399.30695265121,
3137.64857648784,
5.80847765508,
374.23402394886,
0.46268411922,
3.98578825818,
86.04398912724,
16.05857548068,
204.94524478734,
2736.84193438788,
495.32616138678,
475.76987559724
  ],
  [
4043.0896536257,
7415.72476474021,
3039.06605229034,
5.97630596849999,
409.64636857176,
0.420999422399999,
5.21086402044,
94.70094727536,
21.5588025313199,
227.79819933624,
2708.12027152385,
505.670520272608,
483.316979888301
  ],
  [
3598.13284429141,
7317.86276802473,
2846.1651910181,
6.26113715202,
412.580152851659,
0.48353974812,
5.89504961916,
102.0072482082,
25.42716943056,
240.05775513006,
2711.96611313418,
454.88706631646,
432.892324258519
  ],
  [
3754.93540354624,
7511.65923877049,
2800.70818111911,
6.6793685346,
380.261269231019,
0.495524623319999,
6.07585064832,
114.06062251008,
39.85985729862,
276.41099985318,
2645.38509787332,
495.328376085096,
465.28909250104
  ],
  [
4043.59078735007,
8017.18489716505,
2338.95806864845,
6.7875256341,
394.603505735554,
0.51747170688,
6.07585064832,
145.892562054913,
83.1198330814429,
408.732059173849,
2480.44614477944,
427.441506546882,
409.905742992792
  ],
  [
3291.51973731274,
4997.05071692697,
452.188235416201,
63.9709506160571,
446.050495741098,
11.6326046301965,
85.869709014152,
220.181406509467,
609.256812048776,
529.707140310043,
2717.66461431481,
593.564950874224,
388.443809434111
  ],
  [
2885.96717926539,
2676.62515437839,
293.191002866746,
121.154375598014,
498.701133634033,
22.747737553513,
165.663567379984,
293.862964912845,
1131.43400447885,
649.689673274539,
2893.87542604889,
676.605125561303,
339.139457453926
  ],
  [
2664.88017244303,
1096.4584151475,
233.59485578412,
178.337800579971,
543.439537600747,
33.8628704768296,
245.457425745816,
367.884313156941,
1650.85948123489,
769.503145366082,
2732.03449314671,
636.789912347858,
258.105935984877
  ],
  [
2546.12143825256,
383.69776070687,
144.591148980276,
235.521225561928,
587.785639945705,
44.9780034001461,
325.251284111648,
441.672179518208,
2167.12983644434,
889.008654837177,
2379.90569231828,
511.758583755248,
174.052538556381
  ],
  [
2597.56379334278,
275.045700399492,
98.1839204037293,
292.704650543886,
631.738388993547,
56.0931363234626,
405.04514247748,
515.225029663832,
2680.25396805022,
1007.80883971052,
1913.52680335554,
530.552643420933,
153.689961713093
  ],
  [
2749.62249643278,
192.082054109743,
61.7232837841147,
349.888075525843,
681.054211190302,
67.2082692467792,
484.839000843312,
587.790589413631,
3189.00909148252,
1125.32442426428,
1779.67241790878,
550.847796398766,
135.833335875956
  ]
]

//Draw graph
var margin = {
top: 10,
right: 30,
bottom: 30,
left: 70
  },
  width = 960 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

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

let data = []
var group_names = []
//Assumes first line of data is table header, otherwise will not work properly
debugger;
model.output_energy_demand.map(function(x, i) {
  if (i == 0) {
group_names = x
  } else {
let line = {}
x.map(function(y, j) {
  line[group_names[j]] = y
});
data.push(line)
  }
});

/* data.forEach((d, i) => {
  var keys = Object.keys(d)
  d.year = model.year[i];
  for (var j = 0; j < keys.length; j++) {
d[keys[i]] = +d[keys[j]]
  }
}); */

data.forEach((d, i) => {
d['year'] = model.year[i];
});


if (typeof(data) != "undefined") {

  var stackedData = d3.stack()
.keys(group_names)
(data);
debugger;
  //Set up axes
  var x = d3.scaleLinear()
.domain(d3.extent(model.year.map((d, i) => {
  return d
})))
.range([0, width])


  svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(function(d) {
  return d;
}));
  svg.append("text")
.attr("x", width * 0.5)
.attr("y", height + margin.bottom)
.style("text-anchor", "middle")
.attr("font-family", "Tahoma")
.text("Year")

  var y = d3.scaleLinear()
.domain([0, d3.max(stackedData,
  function(d) {
    //Find maximum value of data
    var max = 0;
    d.forEach(function(e, i) {
      if (d3.max(e) > max) max = d3.max(e)
    })
    return max
  })])
.range([height, 0])

  svg.append("g")
.call(d3.axisLeft(y));

  svg.append("text")
.attr("y", -margin.left)
.attr("x", -height * 0.5)
.attr("dy", "1em")
.style("text-anchor", "middle")
.attr("font-family", "Tahoma")
.attr("transform", "rotate(-90)")
.text("Energy Demand (TWh /year)")


  svg
.selectAll("layers")
.data(stackedData)
.enter()
.append("path")
.style("fill", function(d) {
  var n = Math.random() * (16 ** 7 - 1)
  let val = (n.toString(16)).slice(0, 6)
  return `#${val}`;
})

.attr("d", d3.area()
  .x(function(d, i) {
    return x(d.data.year)
  })
  .y0(function(d) {
    return y(d[0])
  })
  .y1(function(d) {
    return y(d[1])
  })
)
} else {
  d3.select("#chart").append("Error loading data")
}
body {
  border: 0;
  margin: 0;
  min-height: 100%;
  width: 100%;
}

h2 {
  font-family: sans-serif;
  font-weight: bold;
  font-size: 28px;
}

#header {
  height: 56px;
  position: relative;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #666666;
}

#header div {
  padding: 5px 0 0 10px;
}

#header span {
  color: #ffffff;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 36px;
  text-shadow: #000000 1px
}

#content {
  margin: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.3.0/d3.min.js"></script>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <!--<link href="css/index.css" rel="stylesheet"/>-->
  <title>Stacked Area Chart</title>
</head>

<body>
  <div id="header">
    <div>
      <span>Stacked Area Chart</span>
    </div>
  </div>
  <div id="content">
    <h2>Demo 1: Basic Graph</h2>
    <div id="chart"></div>
  </div>
  <!--<script type="text/javascript" src="javascripts/stacked_graph1.js"></script>-->
</body>

</html>

Приведенный ниже код искажает данные, поэтому заменил его на более простой код для добавления лет к набору данных.

// Commented below code as it was distorting current dataset
/* data.forEach((d, i) => {
  var keys = Object.keys(d)
  d.year = model.year[i];
  for (var j = 0; j < keys.length; j++) {
d[keys[i]] = +d[keys[j]
  }
}); */

// Use below code.
data.forEach((d, i) => {
    d['year'] = model.year[i];
});

Протестировал данные с Excel и получил тот же результат enter image description here

...