Reputation: 133
I am constructing a stacked area graph (following this tutorial) and am having issues with the graph rendering. The axes render correctly, but the area elements do not appear. When using just one column of the data it works fine, but after stacking the data, no luck.
I feel that the issue is with my use of scaleLinear()
.
I've tried two methods: putting y
values from the d3.stack
function I get negative values out (commented in code below). Secondly, to debug, I set the maximum to the maximum of stackedData
(set to default in code below). This gives all positive values out when I use console.log
, but no graph renders.
Here's the code:
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")
}
Here's the structure of data
:
(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, … }
...
Any ideas?
EDIT: 2020-02-21 I've posted a live version here: https://jsfiddle.net/turium/ywrbkzm9/
Upvotes: 1
Views: 763
Reputation: 8321
I have checked your code and there were couple of errors. I have replaced them with correct one, you can do your R&D on top of it.
Code to show x axis with years without commas.
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>
The below code was messing the data, so replaced it with much easier code to add years to dataset.
// 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];
});
Tested the data with excel and getting the same output
Upvotes: 1