Skip to content

Instantly share code, notes, and snippets.

@tomgp
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomgp/bf14c13fab0daeab3b26 to your computer and use it in GitHub Desktop.
Save tomgp/bf14c13fab0daeab3b26 to your computer and use it in GitHub Desktop.
SAT scores sluggish?
expenditure per pupil sat scores year
3600 840 80
3650 845 81
3700 850 82
3800 840 83
4000 850 84
4100 860 85
4250 880 86
4400 900 87
4495 905 88
<html>
<head>
<title>Dual Y Axes</title>
<script src="http://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 &quot;OR&quot; in the headline to see the same data drawn with different scales.</p>
<p>An example taken from <a href="http://www.sagepub.com/gray/Website%20material/Journals/er_wainer.pdf">Howard Wainer's Understanding Graphs and Tables</a> (figs&nbsp;6&nbsp;&amp;&nbsp;7) for more on the problems of dual y-axes see <a href="http://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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment