Skip to content

Instantly share code, notes, and snippets.

@michalskop
Last active August 29, 2015 13:57
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 michalskop/9633867 to your computer and use it in GitHub Desktop.
Save michalskop/9633867 to your computer and use it in GitHub Desktop.
Pie chart vs. Bar chart fight
name group a1 a2 a3 a4 a5 b1 b2 b3 b4 b5
Person 1 1 0.380952381 0.2857142857 0.1428571429 0.1428571429 0.0476190476 0.35 0.25 0.15 0.2 0.05
Person 2 1 0.3 0.25 0.2 0.2 0.05 0.4 0.3 0.15 0.1 0.05
Person 3 1 0.31 0.23 0.2 0.2 0.06 0.3 0.25 0.18 0.15 0.12
Person 4 1 0.35 0.25 0.15 0.15 0.1 0.3 0.25 0.2 0.15 0.1
Person 5 1 0.4 0.35 0.1 0.1 0.05 0.37 0.25 0.15 0.13 0.1
Person 6 1 0.25 0.2391304348 0.2065217391 0.2065217391 0.097826087 0.2696629213 0.2471910112 0.1685393258 0.1685393258 0.1460674157
Person 7 1 0.375 0.3125 0.125 0.125 0.0625 0.3157894737 0.2631578947 0.1578947368 0.1578947368 0.1052631579
Person 8 1 0.3157894737 0.2631578947 0.1578947368 0.1578947368 0.1052631579 0.2772277228 0.2376237624 0.1782178218 0.1683168317 0.1386138614
Person 9 1 0.4 0.3 0.12 0.12 0.06 0.35 0.25 0.2 0.15 0.05
Person 10 1 0.3076923077 0.2435897436 0.1666666667 0.1666666667 0.1153846154 0.2947368421 0.2736842105 0.1894736842 0.1473684211 0.0947368421
Person 11 1 0.27 0.23 0.2 0.2 0.1 0.29 0.26 0.18 0.15 0.12
Person 12 2 0.2947368421 0.2315789474 0.1789473684 0.2105263158 0.0842105263 0.3 0.25 0.2 0.15 0.1
Person 13 2 0.33 0.22 0.18 0.16 0.11 0.3203883495 0.2330097087 0.1747572816 0.145631068 0.1262135922
Person 14 2 0.2678571429 0.25 0.1696428571 0.1607142857 0.1517857143 0.2857142857 0.2244897959 0.2040816327 0.1530612245 0.1326530612
Person 15 2 0.3296703297 0.3076923077 0.1318681319 0.1648351648 0.0659340659 0.3 0.25 0.2 0.15 0.1
Person 16 2 0.2545454545 0.2363636364 0.1909090909 0.1818181818 0.1363636364 0.3225806452 0.2688172043 0.2150537634 0.1075268817 0.0860215054
Person 17 2 0.35 0.25 0.18 0.1 0.12 0.36 0.3 0.2 0.1 0.04
Person 18 2 0.2967032967 0.2637362637 0.1538461538 0.1758241758 0.1098901099 0.2777777778 0.2333333333 0.1888888889 0.1666666667 0.1333333333
Person 19 2 0.3614457831 0.2048192771 0.1445783133 0.1686746988 0.1204819277 0.2830188679 0.2264150943 0.1886792453 0.1603773585 0.141509434
Person 20 2 0.3333333333 0.2222222222 0.1666666667 0.1666666667 0.1111111111 0.3684210526 0.2631578947 0.2105263158 0.1052631579 0.0526315789
Person 21 2 0.2830188679 0.2358490566 0.1886792453 0.2169811321 0.0754716981 0.4 0.28 0.16 0.1 0.06
Person 22 2 0.3539823009 0.2212389381 0.1769911504 0.1592920354 0.0884955752 0.4838709677 0.3225806452 0.1075268817 0.0537634409 0.0322580645
<!DOCTYPE html>
<meta charset="utf-8">
<style>
g {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: #bbb;
stroke-width: 1px;
opacity: .5;
}
.line.active {
stroke-width: 5px;
stroke: #444
}
.group-2 {
fill: none;
stroke: #bb0;
stroke-width: 1px;
}
.group-2.active {
stroke-width: 5px;
stroke: #880;
}
.zeroline {
fill: none;
stroke: red;
stroke-width: 3px;
}
.pie {
fill: green;
stroke: #222;
opacity: .5;
}
.pie.active {
fill: #222;
opacity: 1;
}
.bar {
fill: blue;
stroke: #222;
opacity: .5;
}
.bar.active {
fill: #222;
opacity: 1;
}
.vertical {
stroke-width: 3px;
opacity: 1;
}
.vertical.bar {
stroke: blue;
}
.vertical.pie {
stroke: green;
}
.vertical.active {
stroke-width: 5px;
}
.group {
font-size: 2em;
}
.g1 {
border:1px solid #bbb;
}
.g2 {
border:1px solid #bb0;
}
.e.pie {
border:3px solid green;
padding: 2px;
opacity: 1;
}
.e.bar {
border:3px solid blue;
padding: 2px;
opacity: 1;
}
p {
font: 1em sans-serif;
}
</style>
<body>
<h1>Pie chart vs. Bar chart figth</h1>
<div id="chart"></div>
<p>
Experiment conducted on 22 university students divided into 2 groups (11 each). Each group was shown 1 pie chart and 1 bar chart showing election results. The students were asked to estimate the percentage won by each party (later rescaled to sum 100%).
</p>
<p>
The chart above summarizes the experiment's results:
<ul>
<li>Every point is one error of estimate (by one student)</li>
<li>Green circles are error of estimates based on a pie chart</li>
<li>Blue squares are error of estimates based on a bar chart</li>
<li>Horizontal lines connect estimates by one person, colored by the election</li>
<li>Vertical lines show variance, the 2 extreme error of estimates in each groups are taken away</li>
<li>Green lines are for error of estimates from pie chart, blue lines are for bar chart</li>
<li>The values on x-axis are slightly randomly moved, so the overlapped points may be visible.</li>
</ul>
</p>
<p>
There is no clear evidence that any of the charts performs better, the results are slightly better for pie charts. But the sample is not big enough for better conclusions.
</p>
<p>The actual file used for the experiment is <a href="https://docs.google.com/document/d/1YqkQzXvi79k_Uoe_MFKD5uWy2oLxvnQkKU7TWc5y4qo/pub">here</a>. The table below shows the experimental design:</p>
<table>
<tr><th></th><th><span class="group g1">Election 1</span></th><th><span class="group g2">Election 2</span></th></th>
<tr><td><span class="group">Group 1:</span></td><td class="e pie"><image src="volby1998_2.png" title="Election 1, pie" /></td><td class="e bar"><image src="volby2002.png" title="Election 2, bar" /></td></tr>
<tr><td><span class="group">Group 2:</span></td><td class="e bar"><image src="volby1998.png" title="Election 1, bar" /></td><td class="e pie"><image src="volby2002_2.png" title="Election 2, pie" /></td></tr>
</table>
<p>The real values were:<br/>
Election 1: 0.2910, 0.2499, 0.1804, 0.1793, 0.0994<br/>
Election 2: 0.3024, 0.2450, 0.1853, 0.1429, 0.1244
</p>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var realvalues = [
[0.2910,0.2499,0.1804,0.1793,0.09935],
[0.3024,0.2450,0.1853,0.1429,0.1244]
];
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([0.05,0.35]);
var y = d3.scale.linear()
.range([height, 0])
.domain([-0.15,0.2]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", x(.35))
.attr("dx", ".71em")
.style("text-anchor", "end")
.text("Real values of percentage");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Errors of Estimates");
var line = d3.svg.line()
.x(
function(d) {
return d[0]; })
.y(function(d) { return d[1]; });
zeroline = Array([x(0.05),y(0)],[x(0.35),y(0)]);
var r = 3;
svg.append("path")
.datum(zeroline)
.attr("class", "zeroline")
.attr("d", line);
d3.csv("data.csv", function(error, data) {
points = [[],[]]; // 2 groups
realvalues.forEach(function(rd,ri) {
pdata = [[],[]]; // 2 chart types
for (i in realvalues[ri]) {
pdata[0][i] = [];
pdata[1][i] = [];
}
data.forEach(function(d) {
rdata = Array();
for (i in realvalues[ri]) {
xx = realvalues[ri][i] + Math.random()/200-0.0025;
if (ri == 0) letter = "a";
else letter = "b";
k = parseInt(i) + 1;
yy = +d[letter+k]-realvalues[ri][i];
rdata.push([x(xx),y(yy)]);
//type of chart:
if (((d.group == "1") && (ri == 0)) || ((d.group == "2") && (ri == 1)))
ct = 1; //bar
else
ct = 0; //pie
points[ct].push([xx,yy]);
pdata[ct][parseInt(i)].push(yy);
}
svg.append("path")
.datum(rdata)
.attr("class", function() {if (ri == 1) return "line group-2"; else return "line"})
.attr("d", line)
.attr("title",d.name)
.on("mouseover", function() {
d3.select(this)
.classed("active", true ) // should then accept fill from CSS
})
.on("mouseout", function() {
d3.select(this)
.classed("active", false)
});
});
//vertical lines
for (ct in pdata) {
for (i in pdata[ct]) {
pdata[ct][i] = pdata[ct][i].sort(compareNumbers);
}
}
//prepare ends (eliminate extremes)
pends = [[],[]]; //2 charts
pmid = [[],[]];
for (ct in pdata) {
for (i in pdata[ct]) {
pends[ct][i] = [];
pends[ct][i].push([x(realvalues[ri][parseInt(i)])+3*parseInt(ct),y(pdata[ct][i][1])]);
pends[ct][i].push([x(realvalues[ri][parseInt(i)])+3*parseInt(ct),y(pdata[ct][i][pdata[ct][i].length-2])]);
pmid[ct][i] = [realvalues[ri], pdata[ct][i][Math.round(pdata[ct][i].length/2-1)]]; //approx, ok for odd numbers
svg.append("path")
.datum(pends[ct][i])
.attr("class", function() {if (ct == "1") return "vertical bar"; else return "vertical pie"})
.attr("d", line)
//.attr("title",d.name)
.on("mouseover", function() {
d3.select(this)
.classed("active", true ) // should then accept fill from CSS
})
.on("mouseout", function() {
d3.select(this)
.classed("active", false)
});
}
}
});
//points
svg.selectAll('circle')
.data(points[0])
.enter().append('circle')
.attr("cx", function(d) {return x(d[0]) })
.attr("cy", function(d) {return y(d[1]) })
.attr("r", 3)
.attr("class", "pie")
.attr("title",function(d) {return "Error of colour estimate: " + Math.round(d[1]*1000)/10 + "% (percentage points)"})
.on("mouseover", function() {
d3.select(this)
.classed("active", true )
})
.on("mouseout", function() {
d3.select(this)
.classed("active", false)
});
svg.selectAll('rect')
.data(points[1])
.enter().append('rect')
.attr("x", function(d) {return x(d[0]) - r })
.attr("y", function(d) {return y(d[1]) - r})
.attr("height", 2*r)
.attr("width", 2*r)
.attr("class", "bar")
.attr("title",function(d) {return "Error of colour estimate: " + Math.round(d[1]*1000)/10 + "% (percentage points)"})
.on("mouseover", function() {
d3.select(this)
.classed("active", true )
})
.on("mouseout", function() {
d3.select(this)
.classed("active", false)
});
});
function compareNumbers(a, b) {
return a - b;
}
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-8592359-13', 'ocks.org');
ga('send', 'pageview');
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment