Reputation: 2617
In the following snippet, I have an extremely simplified streamgraph using hard coded data and minimal styling.
var margin = {top: 20, right: 30, bottom: 0, left: 10},
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var svg = d3.select("body")
.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 data = [{'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0},
{'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2},
{'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3},
{'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6},
{'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5},
{'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0},
{'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0},
{'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0},
{'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0},
{'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9},
{'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6},
{'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8},
{'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9},
{'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0},
{'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9},
{'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5},
{'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9},
{'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7},
{'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0},
{'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1},
{'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1},
{'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1},
{'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5},
{'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9},
{'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3}];
var keys = ['date','bond','active','passive','mmf','other'];
var x = d3.scaleTime()
.domain([new Date('01/01/2014'), new Date('01/01/2022')])
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height*0.8 + ")")
.call(d3.axisBottom(x).tickSize(-height*.7).tickValues([new Date("01/01/2014"),new Date('01/01/2018')]))
.select(".domain").remove()
svg.selectAll(".tick line").attr("stroke", "#b8b8b8")
var y = d3.scaleLinear()
.domain([0, 1000000000])
.range([ height, 0 ]);
var stackedData = d3.stack()
.offset(d3.stackOffsetSilhouette)
.keys(keys)
(data)
var area = d3.area()
.x(function(d) { return x(new Date(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
svg
.selectAll("mylayers")
.data(stackedData)
.enter()
.append("path")
.attr("class", "myArea")
.style("fill", "#003366")
.attr("d", area);
<script src="https://d3js.org/d3.v5.min.js"></script>
As we can see, the graph is not displayed, but at the same time, no errors were flagged.
Given the simplicity of the code and the similarity to the fully functional template seen here, why might this graph not render as expected?
Upvotes: 1
Views: 145
Reputation: 1591
Here's a working example:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
const margin = { top: 20, right: 20, bottom: 20, left: 20 },
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
const svg = d3.select("body")
.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})`);
const parseDate = d3.timeParse('%b-%y');
var data = [{
'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0
},
{
'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2
},
{
'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3
},
{
'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6
},
{
'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5
},
{
'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0
},
{
'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0
},
{
'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0
},
{
'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0
},
{
'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9
},
{
'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6
},
{
'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8
},
{
'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9
},
{
'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0
},
{
'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9
},
{
'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5
},
{
'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9
},
{
'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7
},
{
'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0
},
{
'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1
},
{
'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1
},
{
'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1
},
{
'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5
},
{
'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9
},
{
'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3
}].map(d => {
d['date'] = parseDate(d['date']);
return d;
});
const keys = ['bond', 'active', 'passive', 'mmf', 'other'];
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(
d3.axisBottom(x)
.tickSize(-height)
)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").attr("stroke", "#b8b8b8"));
/*
code from https://observablehq.com/@d3/streamgraph
The d3-shape docs say that d3.stackOffsetWiggle "Shifts the baseline
so as to minimize the weighted wiggle of layers. This offset is recommended
for streamgraphs in conjunction with the inside-out order."
*/
const stackedData = d3.stack()
.order(d3.stackOrderInsideOut)
.offset(d3.stackOffsetWiggle)
.keys(keys)
(data);
// the domain of the y-scale should cover the min and max of the stacked data
// code from https://observablehq.com/@d3/streamgraph
const y = d3.scaleLinear()
.domain([
d3.min(stackedData, d => d3.min(d, d => d[0])),
d3.max(stackedData, d => d3.max(d, d => d[1]))
])
.range([height, 0]);
const color = d3.scaleOrdinal()
.domain(keys)
.range(d3.schemeCategory10);
const area = d3.area()
.x(d => x(d.data.date))
.y0(d => y(d[0]))
.y1(d => y(d[1]));
svg.append('g')
.selectAll("path")
.data(stackedData)
.join("path")
.style("fill", d => color(d.key))
.attr("d", area);
</script>
</body>
Like James's answer says, you should use d3.timeParse
to convert strings into Dates, rather than relying on the Date()
constructor, which is unreliable. In addition, your keys
array should only include the attributes that are being stacked, so it should not contain "date".
I referenced Mike Bostock's streamgraph example for the stack generator and the y-scale. The d3-shape docs for d3.stackOffsetWiggle
say that it "Shifts the baseline so as to minimize the weighted wiggle of layers. This offset is recommended for streamgraphs in conjunction with the inside-out order." I'm following that recommendation rather than using d3.stackOffsetSilhouette
. Lastly, following the example, the domain of the y-scale should cover the min and max of the stacked data.
Upvotes: 3
Reputation: 2393
I think you need to convert your dates into a numeric value so some code like this might help
var dateParser = d3.timeParse('%b-%y')
var area = d3.area()
.x(function(d) { return x(dateParser(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
Upvotes: 2