Created
July 1, 2015 00:52
-
-
Save nikolay-shenkov/3c05dd0ec4b86cdbb968 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function createVis(error, data, completion_type) { | |
// output error message, if any: | |
if (error) { console.log(error); } | |
// use a global variable to store parsed_data | |
// so that we have access to it from other functions | |
data_parsed = data; | |
// set a default completion type: | |
// if completion type is undefined, set it to female completion | |
completion_type = completion_type || "female_completion"; | |
// ------------------------------------- | |
// Create a subset of the data to be used to draw scatter points | |
var data_subset = []; | |
// a function to label countries as extreme or not | |
// extreme = if the difference between male and female completion | |
// is greater than 10% | |
function is_extreme(completion_1, completion_2) { | |
var threshold = 10; | |
return Math.abs(completion_1 - completion_2) > threshold | |
} | |
for (var i = 0; i < data.length; i++) { | |
var new_elem = { | |
"country": data[i]["country"], | |
"gdp_per_capita": data[i]["gdp_per_capita"], | |
"extreme": is_extreme(data[i]["female_completion"], data[i]["male_completion"]), | |
"female_completion": data[i]["female_completion"], | |
"male_completion": data[i]["male_completion"] | |
}; | |
data_subset.push(new_elem); | |
} | |
renderVis(data_subset, completion_type) | |
} | |
function renderVis(data, completion_type) { | |
// bind data to html elements - circles | |
var selection = bodyG.selectAll("circle.country") | |
.data(data, function(d) {return d.country;}); | |
// tooltip formatting function to display tooltip text | |
var tooltip_format = function(country, gdp, female_completion, male_completion) { | |
return country + " GDP: " + (d3.format(".3n"))(gdp) + "$" + | |
"<br>" + "female completion: " + (d3.format(".3n"))(female_completion) + "%" + | |
"<br>" + "male completion: " + (d3.format(".3n"))(male_completion) + "%"; | |
} | |
// enter selection | |
// all points are colored blue by default | |
selection.enter().append("circle") | |
.attr("class", "country") | |
.attr("fill", "steelblue"); | |
function colorPoints(d) { | |
if (d.extreme) | |
return "rgb(183, 32, 81)"; | |
else | |
return "steelblue"; | |
} | |
selection.exit().remove(); | |
// update selection handles animation so we use the duration() | |
// to specify a 2 second transition | |
selection.transition().duration(2000) | |
// we use the log and linear scales to go from | |
// data elements (e.g. gdp per capita) to pixel locations cx and cy | |
.attr("cx", function(d) {return log(d["gdp_per_capita"]);}) | |
.attr("cy", function(d) {return linear(d[completion_type])}) | |
.attr("r", radius) | |
.attr("fill", colorPoints); | |
// specify a tooltip on mouseover | |
bodyG.selectAll("circle.country") | |
.on("mouseover", function(d) { | |
// use a d3.event.target to access the circle element | |
// that is being hovered on | |
d3.select(d3.event.target).transition().duration(200) | |
.attr("fill", "rgb(255, 128, 22)"); | |
tooltip.transition().duration(200).style("opacity", 1); | |
tooltip.html(tooltip_format(d["country"], d["gdp_per_capita"], | |
d["female_completion"], d["male_completion"])) | |
.style("left", (d3.event.pageX + 5) + "px") | |
.style("top", (d3.event.pageY - 10) + "px"); | |
}) | |
.on("mouseout", function(d) { | |
d3.select(d3.event.target).transition().duration(500) | |
.attr("fill", colorPoints(d)); | |
tooltip.transition().duration(500).style("opacity", 0); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
country | female_completion | male_completion | gdp_per_capita | |
---|---|---|---|---|
Algeria | 97.35583 | 95.47622 | 12289.027258652 | |
Argentina | 104.62379 | 100.66476 | 13873.3973747516 | |
Armenia | 103.02998 | 99.7926 | 7161.2441370035 | |
Aruba | 95.14321 | 91.48936 | 40558.4156394559 | |
Austria | 103.69019 | 103.22096 | 43875.8634527672 | |
Azerbaijan | 98.49185 | 97.80458 | 13018.2734364597 | |
Bahamas | 100.88828 | 103.81398 | 25225.1398744822 | |
Barbados | 95.43974 | 88.11736 | 16001.6991077427 | |
Belarus | 92.11484 | 93.55611 | 12872.3053191926 | |
Belgium | 91.54804 | 87.76347 | 41629.864205951 | |
Belize | 95.98029 | 102.45714 | 8074.5799280273 | |
Bolivia | 98.22902 | 98.73953 | 4916.4463328266 | |
Botswana | 96.12179 | 92.22388 | 13354.0627855201 | |
Brunei | 119.28105 | 115.3892 | 75642.526825659 | |
Bulgaria | 97.84627 | 98.70502 | 14277.7716688769 | |
Burkina Faso | 29.07386 | 37.00692 | 1320.8512826941 | |
Burundi | 38.41644 | 45.39401 | 684.1413387599 | |
Cambodia | 90.70509 | 91.22084 | 2300.0155974524 | |
Cameroon | 51.7478 | 62.42028 | 2552.1910686736 | |
Cape Verde | 95.45072 | 90.66958 | 5389.3860432535 | |
Chile | 89.15037 | 102.06293 | 18300.544727773 | |
Colombia | 113.52849 | 109.10287 | 10179.6857083615 | |
Comoros | 64.2246 | 69.74026 | 1427.6538614206 | |
Congo, Dem. Rep. | 40.73085 | 60.14872 | 634.9647187339 | |
Congo, Rep. | 73.75983 | 78.42818 | 4778.3310537773 | |
Costa Rica | 93.9137 | 90.94273 | 11886.2649985042 | |
Cote d'Ivoire | 38.87391 | 56.23429 | 2806.7911809677 | |
Croatia | 100.83056 | 101.30729 | 21999.66217205 | |
Cuba | 91.74624 | 91.71979 | 16898.847345711 | |
Cyprus | 99.95973 | 99.94413 | 32446.93265415 | |
Denmark | 101.73883 | 101.20512 | 45458.6887565343 | |
Dominica | 97.48892 | 92.10526 | 9385.9718784079 | |
Ecuador | 106.17944 | 104.84761 | 8751.4085971644 | |
Egypt | 93.27361 | 98.17595 | 9471.8567039559 | |
El Salvador | 90.53235 | 87.00895 | 7373.386032085 | |
Eritrea | 41.15218 | 52.72595 | 1238.7070714377 | |
Estonia | 98.15987 | 99.56909 | 25545.6192270155 | |
Ethiopia | 43.08178 | 53.5593 | 862.9580679191 | |
Fiji | 103.49723 | 102.24421 | 7310.197791402 | |
Finland | 98.42159 | 98.21577 | 42137.1452843968 | |
Gambia | 73.26979 | 71.59998 | 1502.6924943453 | |
Georgia | 92.07035 | 96.20418 | 5735.0966766016 | |
Germany | 103.12148 | 102.38585 | 41056.4935311553 | |
Ghana | 75.4757 | 80.22254 | 2718.7657368381 | |
Greece | 100.49263 | 101.3603 | 32359.9090125418 | |
Grenada | 98.22596 | 97.06691 | 12023.1007427025 | |
Guatemala | 74.03614 | 80.62982 | 6899.3281952802 | |
Guinea | 54.53389 | 72.61478 | 1192.6101476025 | |
Guyana | 102.00366 | 95.2538 | 5069.8721341213 | |
Hong Kong, China | 101.19709 | 101.59161 | 46028.7878896375 | |
Hungary | 95.01021 | 96.45459 | 23316.5642698646 | |
Iceland | 96.95633 | 96.89337 | 44510.3862304649 | |
India | 92.4569 | 96.08657 | 3828.4101334308 | |
Indonesia | 101.14018 | 103.40563 | 7116.6998217769 | |
Iran | 95.36778 | 96.08603 | 14549.674156445 | |
Iraq | 55.39513 | 74.4742 | 11614.5107574296 | |
Israel | 104.9814 | 102.1888 | 27913.4445067022 | |
Italy | 100.97996 | 101.56501 | 38610.1930368561 | |
Jamaica | 85.36357 | 83.32319 | 8967.3775831749 | |
Jordan | 104.2686 | 103.60543 | 10393.5387070097 | |
Kazakhstan | 102.02182 | 100.826 | 18329.6768934656 | |
Kiribati | 104.27948 | 138.58333 | 1781.9579747226 | |
Kuwait | 114.22918 | 110.15804 | 102060.798623929 | |
Latvia | 92.05514 | 95.76749 | 22045.6755474358 | |
Lebanon | 87.7129 | 83.49108 | 12744.7570667222 | |
Lesotho | 81.54746 | 60.16019 | 1980.7097312589 | |
Liberia | 63.13395 | 74.85203 | 640.2942969144 | |
Lithuania | 95.97445 | 95.38484 | 21275.1386445689 | |
Macao, China | 96.8486 | 99.05603 | 79875.4769183965 | |
Macedonia, FYR | 92.85767 | 92.81246 | 10367.1381181208 | |
Madagascar | 62.31528 | 62.80986 | 1449.9454430682 | |
Malawi | 59.84461 | 58.76665 | 642.5597294405 | |
Mali | 40.1807 | 56.36193 | 1572.3480839379 | |
Malta | 95.04831 | 96.6348 | 27172.2250562066 | |
Marshall Islands | 119.12351 | 113.39623 | 3436.4504161557 | |
Mauritania | 56.72536 | 56.67185 | 2678.5330715377 | |
Mauritius | 95.6031 | 92.44457 | 13667.1513935432 | |
Mexico | 104.13633 | 103.08345 | 16206.3244596671 | |
Moldova | 92.87085 | 92.95444 | 3585.0677220772 | |
Mongolia | 109.32974 | 106.9648 | 6385.2413771627 | |
Morocco | 79.80282 | 87.30273 | 5825.4031883929 | |
Mozambique | 39.04196 | 52.51468 | 810.1118916146 | |
Myanmar | 99.71613 | 93.35262 | 2846.230357341 | |
Namibia | 86.06281 | 77.12673 | 8042.89339644 | |
Nicaragua | 79.79047 | 72.83059 | 3986.1928627597 | |
Niger | 31.58022 | 47.03505 | 769.2240545399 | |
Nigeria | 71.96312 | 89.86682 | 4382.2164558205 | |
Norway | 97.51715 | 97.20876 | 65044.59870358 | |
Pakistan | 53.49888 | 67.53208 | 4216.7751613046 | |
Panama | 98.46349 | 97.50738 | 12814.659858148 | |
Paraguay | 95.54136 | 93.84992 | 6453.3096243645 | |
Peru | 103.34836 | 103.60842 | 8609.3719582645 | |
Philippines | 94.67851 | 88.94463 | 5155.8645440919 | |
Qatar | 97.81575 | 106.14365 | 125625.606269164 | |
Romania | 116.01544 | 114.85452 | 17010.999147557 | |
Samoa | 108.76242 | 107.43632 | 5662.4806412001 | |
Sao Tome and Principe | 73.22154 | 70.07444 | 2384.6063270466 | |
Saudi Arabia | 92.23329 | 94.55005 | 40949.5304450474 | |
Senegal | 50.54852 | 53.70338 | 2123.5023668099 | |
Serbia | 100.68998 | 100.35878 | 12536.1500490148 | |
Seychelles | 120.59748 | 118.76833 | 21641.6413452145 | |
Slovak Republic | 93.1476 | 92.81648 | 23788.7100585809 | |
Spain | 98.64053 | 98.77576 | 34477.7995197823 | |
Sri Lanka | 101.52506 | 101.69981 | 6518.3431999269 | |
Suriname | 80.92048 | 72.04956 | 13484.5781250747 | |
Swaziland | 70.77358 | 75.69924 | 6251.9150067393 | |
Sweden | 95.91131 | 95.44557 | 43574.8860156294 | |
Switzerland | 93.77574 | 91.54495 | 54581.8997228911 | |
Syria | 103.02075 | 104.0705 | 6093.6236925529 | |
Tajikistan | 92.80384 | 96.9551 | 1864.8506264769 | |
Tanzania | 81.36033 | 85.1121 | 1383.8006538396 | |
Trinidad and Tobago | 93.38731 | 92.81595 | 30246.5474249106 | |
Tunisia | 101.51381 | 104.55751 | 9584.5811448304 | |
Turkey | 93.24417 | 98.44286 | 16633.6004186782 | |
Uganda | 51.26265 | 55.88286 | 1168.6341159396 | |
Ukraine | 102.17759 | 101.93806 | 8530.3907998738 | |
United States | 101.44458 | 98.99668 | 51136.3700877917 | |
Uruguay | 105.73136 | 102.86746 | 14153.5126626263 | |
Uzbekistan | 96.42169 | 98.39212 | 3413.6822577465 | |
Vanuatu | 83.37147 | 80.20796 | 2816.0438714665 | |
Venezuela | 99.89733 | 95.69116 | 17279.8346380165 | |
West Bank and Gaza | 86.80834 | 86.63195 | 4014.5956833598 | |
Zambia | 86.88768 | 98.40848 | 3096.2364213116 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Female/Male School Completion vs GDP per capita</title> | |
<link rel="stylesheet" type="text/css" href="styles.css"/> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
</head> | |
<body> | |
<header id="title-container"> | |
<h1 id="title">Gender inequality in primary school completion</h1> | |
</header> | |
<section id="scatter-container"></section> | |
<div id="buttons-container"> | |
<button id="girls" class="buttons">Girls</button> | |
</br> | |
<button id="boys" class="buttons">Boys</button> | |
</div> | |
<div id="notes-container"> | |
<p class="metrics">Primary school completion rate is the percentage of female or male students completing the last year of primary school. The ratio can exceed 100% due to over-aged and under-aged children.</p> | |
<p class="metrics">In this visualization color and motion display the difference between femaile and male completion rates for each country. Colors are encoded as follows:</p> | |
</div> | |
<footer><h2>References:</h2> | |
<ol> | |
<li>Data from <a href="http://www.gapminder.org/data/">Gapminder</a></li> | |
<li><a href="http://bl.ocks.org/weiglemc/6185069">Scatterplot example in d3</a></li> | |
<li><a href="http://zeroviscosity.com/d3-js-step-by-step/step-5-adding-tooltips">Adding tooltips to a visualization</a></li> | |
<li><a href="http://bl.ocks.org/zanarmstrong/raw/05c1e95bf7aa16c4768e/">Interactive number formatter in d3</a></li> | |
</ol> | |
</footer> | |
<script src="initialize_figure.js"></script> | |
<script src="create_vis.js"></script> | |
</body> | |
<script> | |
d3.csv("data/edu-gdp.csv", function(d) { | |
d["gdp_per_capita"] = +d["gdp_per_capita"]; | |
d['female_completion'] = +d['female_completion']; | |
d["male_completion"] = +d["male_completion"]; | |
return d; | |
}, createVis); | |
</script> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// global variable to hold data once we load it with d3.csv | |
var data_parsed; | |
var height = 600, width = 850, | |
margin = 50, radius = 10; | |
// create the svg element that contains visualization | |
var svg = d3.select("#scatter-container").append("svg") | |
.attr("id", "scatter") | |
.attr("width", width + 2*margin) | |
.attr("height", height); | |
// change svg background from white to light gray | |
svg.append("rect") | |
.attr("width", "100%") | |
.attr("height", "100%") | |
.attr("fill", "rgb(240, 232, 226)"); | |
// keep scale ranges constant | |
var minX = 635, minY = 29.1, maxX = 126000, maxY = 130; | |
// create two scales - linear (y) and logarithmic (x) | |
var log = d3.scale.log() | |
.domain([minX - 100, maxX]) | |
.range([0, width - 2*margin]); | |
var linear = d3.scale.linear() | |
.domain([minY - 5, maxY + 10]) | |
.range([height - 2*margin, 0]); | |
// a "g" element to hold axes | |
var axesG = svg.append("g").attr("class", "axes"); | |
// create axis elements | |
var xAxis = d3.svg.axis().scale(log).orient("bottom") | |
.tickValues([1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000]) | |
.tickFormat(d3.format(".1e")) | |
yAxis = d3.svg.axis().scale(linear).orient("left"); | |
// helper function to create the "translate(x, y)" string | |
function translator(x, y) { | |
return "translate(" + x + "," + y + ")"; | |
} | |
// append axes elements to axesG container | |
axesG.append("g") | |
.attr("class", "y-axis all-axis") | |
// location for the y-axis: margin, margin | |
.attr("transform", translator(margin, margin)) | |
.call(yAxis) | |
// add y-axis label | |
.append("text") | |
.attr("id", "y-axis") | |
.attr("class", "axis-label") | |
// rotate text so that it is vertical | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
// position text appropriately along the axis | |
.style("text-anchor", "end") | |
// finally, specify the actual label | |
.text("Primary school completion male/female"); | |
axesG.append("g") | |
.attr("class", "x-axis all-axis") | |
.attr("transform", translator(margin, height - margin)) | |
.call(xAxis) | |
.append("text") | |
.attr("id", "x-label") | |
.attr("class", "axis-label") | |
.attr("x", width - 2*margin) | |
.attr("y", -6) | |
.style("text-anchor", "end") | |
.text("Income per person (GDP/capita $)");; | |
// add grid-lines for the x-axis | |
d3.selectAll("g.x-axis g.tick") | |
.append("line") | |
.classed("grid-line", true) | |
// they start at (0, 0) and go to (0, height - 2*margin) | |
.attr("x1", 0) | |
.attr("y1", 0) | |
.attr("x2", 0) | |
.attr("y2", - (height - 2*margin)); | |
// add tooltip, but make it transparent for now | |
var tooltip = d3.select("body").append("div") | |
.attr("class", "tooltip") | |
.style("opacity", 0); | |
// container for the scatter points | |
var bodyG = svg.append("g") | |
.attr("class", "scatter-g") | |
.attr("transform", translator(margin, margin)); | |
// -------------------------------------- | |
// Creating buttons and binding data to them | |
// note the "completion" field in each of the objects | |
var buttonsData = [{"text": "Girls", "completion": "female_completion"}, | |
{"text": "Boys", "completion": "male_completion"}]; | |
// bind the buttons (girls and boys) to data | |
var buttons_selection = d3.selectAll(".buttons").data(buttonsData) | |
// make girls button look active (pressed) | |
// we are using a 1 sec (1000 ms) transition for a smooth effect | |
d3.select("#girls").transition().duration(1000). | |
style("background", "steelBlue").style("color", "white"); | |
// and boys button look inactive (not pressed) | |
d3.select("#boys").transition().duration(1000) | |
.style("background", "rgb(220, 244, 252)").style("color", "black") | |
// note that it is partially transparent | |
.style("opacity", 0.6); | |
// declare a click handler for both of the buttons | |
buttons_selection.on("click", function(d) { | |
// make both buttons look inactve | |
d3.selectAll(".buttons").transition().duration(500) | |
.style("background", "rgb(220, 244, 252)").style("color", "black") | |
.style("opacity", 0.6); | |
// make the button that is pressed (we can access it using the this parameter) | |
// look pressed | |
d3.select(this).transition().duration(500) | |
.style("background", "steelBlue").style("color", "white") | |
.style("opacity", 1); | |
// finally call the createVis function to update the visualization! | |
createVis(null, data_parsed, d.completion); | |
}); | |
function addLegend() { | |
var legend_svg = d3.select("#notes-container").append("svg") | |
.attr("id", "legend") | |
.attr("width", 350) | |
.attr("height", 80); | |
var legendG = legend_svg.append("g").attr("id", "lengendG"); | |
var legend_data = [ | |
{"text": "- difference between completions <10%", | |
"location": 0, "fill": "steelblue"}, | |
{"text": "- difference between completions >10%", | |
"location": 50, "fill": "#b72051"} | |
]; | |
var cx = 10, cy_offset = 10, radius = 10, text_offset = 30, | |
alpha = 0.7; | |
var selection = legendG.selectAll("circle.items").data(legend_data); | |
selection.enter().append("circle") | |
.attr("class", "items") | |
.attr("fill", function(d) { return d["fill"];} ) | |
.attr("cx", cx) | |
.attr("cy", function(d) {return d["location"] + cy_offset;} ) | |
.attr("r", radius) | |
.attr("opacity", alpha) | |
var textLabels = legendG.selectAll("text").data(legend_data) | |
.enter().append("text") | |
.attr("x", text_offset) | |
.attr("y", function(d) {return d["location"] + cy_offset + radius/2;} ) | |
.text(function(d) {return d["text"]; }) | |
.attr("font-size", "18px") | |
.attr("font-family", "Helvetica"); | |
} | |
addLegend(); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#scatter-container { | |
width: 70%; | |
float: left; | |
margin-left: 50px; | |
} | |
#buttons-container { | |
margin-top: 50px; | |
margin-left: 50px; | |
} | |
.buttons { | |
font-size: 22px; | |
margin-bottom: 30px; | |
font-family: Verdana; | |
border-radius: 10px; | |
} | |
#title { | |
font-family: Verdana; | |
text-align: center; | |
font-size: 30px; | |
font-weight: normal; | |
} | |
footer { | |
width: 100%; | |
float: left; | |
display: block; | |
} | |
.all-axis path, | |
.all-axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.country { | |
opacity: 0.6; | |
} | |
.grid-line { | |
opacity: 0.2; | |
} | |
.tooltip { | |
position: absolute; | |
width: 350px; | |
font-size: 20px; | |
font-family: sans-serif; | |
pointer-events: none; | |
text-align: center; | |
} | |
.metrics, ol { | |
font-size: 18px; | |
font-family: Helvetica; | |
} | |
h2 { | |
font-family: Verdana; | |
font-weight: normal; | |
font-size: 20px; | |
} | |
footer { | |
margin-left: 50px; | |
margin-bottom: 20px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment