D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
tomgp
Full window
Github gist
SAT scores sluggish?
<html> <head> <title>Dual Y Axes</title> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> <style type="text/css"> body{ font-family: sans-serif; } .domain{ fill:none; stroke:#000; shape-rendering:crispEdges; } .plot{ fill:none; stroke-width:2; } .cost-scale .tick{ fill:#F00; } .sat-scale .tick{ fill:#00F; } .hidden{ display:none; } .notes{ max-width: 600px; } </style> </head> <body> <h1 class="active">SAT scores remain sluggish despite funding increase <a href="#" data-satDomain="800,1200" data-costDomain="2800,4800">(OR...)</a></h1> <h1 class="hidden">SAT scores soar despite sluggish funding <a href="#" data-satDomain="800,910" data-costDomain="0,20000">(OR...)</a></h1> <div class="chart"></div> <div class="notes"> <p>Why dual axis charts are a bad idea.</p> <p>Click on the "OR" in the headline to see the same data drawn with different scales.</p> <p>An example taken from <a href="https://www.sagepub.com/gray/Website%20material/Journals/er_wainer.pdf">Howard Wainer's Understanding Graphs and Tables</a> (figs 6 & 7) for more on the problems of dual y-axes see <a href="https://www.perceptualedge.com/articles/visual_business_intelligence/dual-scaled_axes.pdf">Steven Few's Dual-Scaled Axes in Graphs Are They Ever the Best Solution?</a></p></div> </body> <script type="text/javascript"> var height=500, width=800, margin={ top:50, left:150, bottom:70, right:100 }, axisGap = 5, plotWidth = width-(margin.left+margin.right), plotHeight = height-(margin.top+margin.bottom); var satDomain = [0,1000]; var costDomain = [0,5000]; var data =[]; var container = d3.select('.chart') .append('svg') .attr({ width:width, height:height }) .append('g') .attr({ 'transform':'translate(' + margin.left + ',' + margin.top + ')' }); container.append('g').attr({ 'class':'sat-scale', 'transform':'translate('+ (plotWidth + axisGap) +',0)' }); container.append('g').attr({ 'class':'cost-scale', 'transform':'translate('+ (- axisGap) +',0)' }); container.append('g').attr({ 'class':'time-scale', 'transform':'translate(0,' + (plotHeight + axisGap) + ')' }); var plot = container.append('g').attr({ 'class':'plot' }); plot.append('path').attr({ 'class':'sat-line' }); plot.append('path').attr({ 'class':'cost-line' }); var labels = container.append('g') .attr('class','labels') labels.append('text') .attr({ fill:'#F00', 'transform':'translate(0,'+(-axisGap*4)+')', 'text-anchor':'end' }).text('Expenditure/ pupil $'); labels.append('text') .attr({ fill:'#00F', 'transform':'translate(' + plotWidth + ','+(-axisGap*4)+')' }).text('SAT score'); labels.append('text') .attr({ 'transform':'translate(' + plotWidth/2 + ','+(plotHeight + axisGap*10)+')' }).text('year'); function getDomains(){ var d = d3.select('h1.active a').node().dataset; satDomain = d.satdomain.split(',').map(function(d){return Number(d); }); costDomain = d.costdomain.split(',').map(function(d){return Number(d); }); } function drawChart(){ var costScale = d3.scale.linear() .range([plotHeight, 0]) .domain(costDomain), satScale = d3.scale.linear() .range([plotHeight, 0]) .domain(satDomain), timeScale = d3.scale.linear() .range([0,plotWidth]) .domain(d3.extent(data, function(d){ return d.year; })), leftAxis = d3.svg.axis() .scale(costScale) .orient('left'), rightAxis = d3.svg.axis() .scale(satScale) .orient('right'), timeAxis = d3.svg.axis() .scale(timeScale) .orient('bottom'), costLine = d3.svg.line() .x(function(d) { return timeScale(d.year); }) .y(function(d) { return costScale(d['expenditure per pupil']); }); satLine = d3.svg.line() .x(function(d) { return timeScale(d.year); }) .y(function(d) { return satScale(d['sat scores']); }); d3.select( '.sat-scale' ).call( rightAxis ); d3.select( '.cost-scale' ).call( leftAxis ); d3.select( '.time-scale' ).call( timeAxis ); d3.select( '.cost-line' ) .datum(data) .transition() .attr({ 'd': costLine, 'stroke':'#F00', 'stroke-width': 2 }); d3.select(' .sat-line ') .datum(data) .transition() .attr({ 'd': satLine, 'stroke':'#00F', 'stroke-width': 2 }); } d3.selectAll('a').on('click',function(d){ console.log(this); //toggle h1s d3.selectAll('h1') .attr({ 'class':function(){ if (d3.select(this).classed('hidden')){ return 'active'; } return 'hidden'; } }) getDomains(); drawChart(); }) d3.csv('data.csv', function(d){ data = d; getDomains(); drawChart(); }) </script> </html>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js