Skip to content

Instantly share code, notes, and snippets.

@noellethenerd
Last active January 25, 2019 17:09
Show Gist options
  • Save noellethenerd/1cd2ed706e53abaff3f9482b578d0175 to your computer and use it in GitHub Desktop.
Save noellethenerd/1cd2ed706e53abaff3f9482b578d0175 to your computer and use it in GitHub Desktop.
WDVP_ambclimpol
license: mit
State Ambitious Climate Policy Left-Wing Government EU Membership Political Constraints Ecological Footprint HPI Population
Australia 0.46 0.75 0 0.22 9.31 21.22896631 22728254
Austria 0 0.43 1 0.84 6.06 30.47822433 8429991
Belgium 0.4 0.36 1 0.62 7.44 23.72652343 11128246
Canada 0 0 0 0.83 8.17 23.94183384 34751476
Denmark 0.93 0.14 1 1 5.51 32.67258209 5591572
Finland 0.45 0.32 1 0.69 5.87 31.29336395 5413971
France 0.92 0.07 1 0 5.14 30.41350606 65639975
Germany 1 0.29 1 0.74 5.3 29.81550359 80425823
Greece 0.24 0.36 1 0.41 4.38 23.62099962 11045011
Iceland 1 0.64 0.66 0.86 6.425540806 31.07872474 320716
Ireland 1 0.21 1 1 5.57 30.01652957 4586897
Italy 0.09 0.25 1 0.67 4.61 28.0765247 59539717
Japan 0.03 0.07 0 0.9 5.02 28.31934808 80425823
Luxembourg 0.37 0.5 1 0.51 15.82 13.1511742 530946
Netherlands 0.29 0.25 1 0.72 5.28 35.31545093 16754962
New Zealand 0.18 0.39 0 0.7 5.6 31.2583395 4408100
Norway 1 0.75 0.66 0.3 4.98 36.82705238 5018573
Portugal 1 0.79 1 0.15 3.88 24.84739373 10514844
Spain 0.5 0.82 1 0.81 3.67 35.95897674 46773055
Sweden 1 0.11 1 0.73 7.25 28.03492519 9519374
Switzerland 0.74 0.25 0.66 0.56 5.79 34.33096962 7996861
United Kingdom 1 0.64 1 1 4.94 31.90928632 63700300
United States of America 0 0 0 0.31 8.22 20.74637758 80425823
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
<h1>Ecological Growth & Ambition</h1>
<h2>
<u>ecological footprint</u><br>
& <u>climate policy ambition</u><br>
across developed states
</h2>
<p>visualisations by <a href="http://noellethenerd.com/">noelle aly</a></p>
<p>data from <a href="https://www.research.manchester.ac.uk/portal/files/53356041/Climate_policy_in_developed_states_clean_March.docx">dr. paul tobin</a></p>
<p>& <a href="http://happyplanetindex.org/countries">happy planet index</a></p>
<style>
h1 {
font-size: 45px;
}
head {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
body {
background-image: url("http://res.publicdomainfiles.com/pdf_view/99/13949481012352.jpg")
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
p {
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
text-align: center;
}
svg {
font-family: Arial, Helvetica, sans-serif;
}
.stop-left {
stop-color: #fde0dd; /* Indigo */
}
.stop-right {
stop-color: #fa9fb5; /* Teal */
}
.stop-left2 {
stop-color: #dde0fd; /* Indigo */
}
.stop-right2 {
stop-color: #a79ef9; /* Teal */
}
.stop-left3 {
stop-color: #8e7662; /* Indigo */
}
.stop-right3 {
stop-color: #513a27; /* Teal */
}
.filled {
fill: url(#mainGradient1);
}
.filled2 {
fill: url(#mainGradient2);
}
.deadColours {
fill: url(#deadColours);
}
.outlined {
fill: none;
stroke: url(#mainGradient);
stroke-width: 4;
}
.text {
paint-order: stroke;
stroke: #ffffff;
stroke-width: 2px;
stroke-linecap: butt;
stroke-linejoin: miter;
font-weight: 800;
}
</style>
</head>
<body>
<svg></svg>
<div id="key-container" width="1000" height="690"></div>
<div id="svg-container"></div>
<script>
//////////////// keys
const WIDTH = 750;
const padding = 20;
const width = 150;
const height = 200;
const legendSvg = d3
.select("#key-container")
.append("svg")
.attr('width', 1000)
.attr('height', 1000)
.append('g')
.attr("transform", "translate(" + [padding + 20, padding] + ")");
legendData = [
// ambitious examples
{
"Ambitious Climate Policy": "0",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "Less Ambitious"
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: " "
},
{
"Ambitious Climate Policy": "1",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "Ambitious Climate Policy"
},
// footprint examples
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "3.67",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "Lower Footprint"
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: " "
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "15.82",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "Higher Footprint"
},
// eu membership
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "0",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "Non EU"
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "0.66",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: " "
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: "EU Member"
},
// Degree of Polticial Contraints
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0",
Population: "22728254",
State: "Low Political Constraints"
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.62",
Population: "22728254",
State: " "
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "1",
Population: "22728254",
State: "High Polticial Contraints"
},
// left wing government
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.79",
"Political Constraints": "0.6",
Population: "22728254",
State: "Left-Wing Government"
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0.36",
"Political Constraints": "0.6",
Population: "22728254",
State: " "
},
{
"Ambitious Climate Policy": "0.55",
"EU Membership": "1",
"Ecological Footprint": "6",
"Left-Wing Government": "0",
"Political Constraints": "0.6",
Population: "22728254",
State: "Right-Wing Government"
},
];
////// main body
const svg = d3
.select("svg")
.attr('width', 1000)
.attr('height', 1100)
.append("g")
.attr("transform", "translate(" + [padding, padding] + ")");
//////////////
// colours
const div = d3.select("#svg-container"),
svg2 = div.append("svg");
// Create the svg:defs element and the main gradient definition.
const svgDefs = svg2.append("defs");
const mainGradient1 = svgDefs
.append("linearGradient")
.attr("id", "mainGradient1");
const mainGradient2 = svgDefs
.append("linearGradient")
.attr("id", "mainGradient2");
const deadColours = svgDefs
.append("linearGradient")
.attr("id", "deadColours");
// Create the stops of the main gradient. Each stop will be assigned
// a class to style the stop using CSS.
mainGradient1
.append("stop")
.attr("class", "stop-left")
.attr("offset", "0");
mainGradient1
.append("stop")
.attr("class", "stop-right")
.attr("offset", "1");
mainGradient2
.append("stop")
.attr("class", "stop-left2")
.attr("offset", "0");
mainGradient2
.append("stop")
.attr("class", "stop-right2")
.attr("offset", "1");
deadColours
.append("stop")
.attr("class", "stop-left3")
.attr("offset", "0");
deadColours
.append("stop")
.attr("class", "stop-right3")
.attr("offset", "1");
const flowerSize = 150;
const petalPaths = [
// smileyface
// ["M74.5,148 C33.9070709,148 1,115.092929 1,74.5 C1,33.9070709 33.9070709,1 74.5,1 C115.092929,1 148,33.9070709 148,74.5 C148,115.092929 115.092929,148 74.5,148 Z M39,104.933594 L71.6808903,126.340194 L104.361781,104.933594 L39,104.933594 Z M49.5,76 C52.5375661,76 55,68.3888407 55,59 C55,49.6111593 52.5375661,42 49.5,42 C46.4624339,42 44,49.6111593 44,59 C44,68.3888407 46.4624339,76 49.5,76 Z M98.5,76 C101.537566,76 104,68.3888407 104,59 C104,49.6111593 101,42 98,42 C95,42 93,49 93,59 C93,68 95,76 98,76 Z"],
[
"M0,0",
"C50,40 50,70 20,100",
"L0,85",
"L-20,100",
"C-50,70 -50,40 0,0"
],
["M0,0", "C50,50 50,100 0,100", "C-50,100 -50,50 0,0"],
["M0,0", "C50,25 50,75 0,100", "C-50,75 -50,25 0,0"]
];
const numPetalScale = d3.scaleQuantize().range(_.range(4, 8));
const flowerSizeScale = d3.scaleLinear().range([0.2, 0.55]); //ambclipl
const petalScale = d3.scaleOrdinal().range(_.range(4));
const petalColourScale = d3
.scaleOrdinal()
.range(["filled", "deadColours", "filled2"]);
const xPosition = d3
.scaleLinear()
.range([50, (WIDTH - flowerSize)]);
const circleColourScale = d3
.scaleOrdinal()
.range(["#fff482", "#82ffd7", "#82d3ff"]);
svg
.append("text")
.text("Smaller Populations")
.attr("x", 10)
.attr("y", 10);
svg
.append("text")
.text("Larger Populations")
.attr("x", WIDTH - flowerSize*1.3)
.attr("y", 10);
d3.csv("./climate-stats.csv", d => {
console.log(d);
dataset = d.reduce((acc, curr) => {
let item = {};
for (i in curr) {
if (curr[i] == 0 || Number(curr[i])) {
item[i] = Number(curr[i]);
} else {
item[i] = curr[i];
}
}
acc.push(item);
return acc;
}, []);
// Number of petals depends on political constraints
const minPC = d3.min(dataset, d => d["Political Constraints"]);
const maxPC = d3.max(dataset, d => d["Political Constraints"]);
numPetalScale.domain([minPC, maxPC]);
console.log("min max pol constraints", minPC, maxPC, !isNaN(minPC));
// Colour of petals depends on Ecological Footprint
const minFootprint = d3.min(dataset, d => d["Ecological Footprint"]);
const maxFootprint = d3.max(dataset, d => d["Ecological Footprint"]);
petalColourScale.domain([minFootprint, maxFootprint]);
console.log(petalColourScale(minFootprint), petalColourScale(maxFootprint));
// x Position dependent on Population Size
const minPop = d3.min(dataset, d => d.Population);
const maxPop = d3.max(dataset, d => d.Population);
xPosition.domain([minPop, maxPop]);
console.log("min max populations", minPop, maxPop, !isNaN(minPop));
// Colour of inner circle dependent on LW/RW Government
const minLW = d3.min(dataset, d => d["Left-Wing Government"]);
const maxLW = d3.max(dataset, d => d["Left-Wing Government"]);
circleColourScale.domain([minLW, maxLW]);
console.log("min max LW", minLW, maxLW, !isNaN(minLW));
// Flower size dependent on Ambitious Climate Policy
const minACP = d3.min(dataset, d => d["Ambitious Climate Policy"]);
const maxACP = d3.max(dataset, d => d["Ambitious Climate Policy"]);
flowerSizeScale.domain([minACP, maxACP]);
console.log("min max amblcpl", minACP, maxACP, !isNaN(minACP));
// EU Membership determines shapes of petals
// draw flower for each country
const flowers = svg
.selectAll("g.flower")
.data(_.values(dataset))
.enter()
.append("g")
.classed("flower", true)
.attr("transform", function(d, i) {
// position flower based on pop size
const x = xPosition(d.Population);
console.log(d.State, d.Population, xPosition(d.Population))
const y = (i / 4) * flowerSize + 30;
const scale = flowerSizeScale(d["Ambitious Climate Policy"]);
return (
"translate(" +
x*(i%5*.5) +
"," +
y +
")scale(" +
scale +
")"
);
});
flowers
.selectAll("path")
.data(function(d) {
const numPetals = numPetalScale(d["Political Constraints"]);
const path = petalPaths[petalScale(d["EU Membership"])];
const colour = petalColourScale(d["Ecological Footprint"]);
return _.times(numPetals, function(i) {
return {
angle: (360 / numPetals) * i + 10,
path: path,
colour: colour,
name: d.State
};
});
})
.enter()
.append("path")
.attr("stroke", "#000")
.attr("stroke-width", 0.5)
.attr("class", d => d.colour)
.attr("d", function(d) {
return d.path;
})
.attr("transform", function(d) {
const cx = flowerSize / 2;
const cy = flowerSize / 2;
return "translate(" + [cx, cy] + ")rotate(" + [d.angle] + ")";
});
flowers
.append("text")
.text(d => d.State.toUpperCase())
.attr("font-size", 14)
.attr("class", "text")
.attr("transform", function(d, i) {
// position flower based on pop size
const scale = 1 / flowerSizeScale(d["Ambitious Climate Policy"]);
return "translate(" + -10 + "," + -15 + ")scale(" + scale + ")";
});
// position center of flower
const circles = flowers
.selectAll("circle")
.data(function(d) {
const colour = circleColourScale(d["Left-Wing Government"]);
return [{ colour: colour, x_axis: 75, y_axis: 75, radius: 20 }];
})
.enter()
.append("circle");
const circleAttributes = circles
.attr("cx", function(d) {
return d.x_axis;
})
.attr("cy", function(d) {
return d.y_axis;
})
.attr("r", function(d) {
return d.radius;
})
.attr("stroke", "#000")
.attr("stroke-width", 2)
.attr("fill", d => d.colour);
//////////////////////
// LEGEND FLOWERS
svg.append("text")
.text('legend'.toUpperCase())
.attr("font-size", 25)
.attr("class", "text")
.attr('y', 1030)
;
const legend = legendSvg
.selectAll("g.flower")
.data(_.values(legendData))
.enter()
.append("g")
.classed("flower", true)
.attr("transform", function(d, i) {
// position flower based on pop size
const x = (i % 3) * flowerSize;
const y = Math.floor(i / 3) * flowerSize;
const scale = flowerSizeScale(d["Ambitious Climate Policy"]);
return (
"translate(" +
(x) +
"," +
y +
")scale(" +
scale +
")"
);
});
legend
.selectAll("path")
.data(function(d) {
const numPetals = numPetalScale(d["Political Constraints"]);
const path = petalPaths[petalScale(d["EU Membership"])];
const colour = petalColourScale(d["Ecological Footprint"]);
return _.times(numPetals, function(i) {
return {
angle: (360 / numPetals) * i + 10,
path: path,
colour: colour,
name: d.State
};
});
})
.enter()
.append("path")
.attr("stroke", "#000")
.attr("stroke-width", 0.5)
.attr("class", d => d.colour)
.attr("d", function(d) {
return d.path;
})
.attr("transform", function(d) {
const cx = flowerSize / 2;
const cy = flowerSize / 2;
return "translate(" + [cx, cy] + ")rotate(" + [d.angle] + ")";
});
legend
.append("text")
.text(d => d.State.toUpperCase())
.attr("font-size", 12)
.attr("class", "text")
.attr("transform", function(d, i) {
// position flower based on pop size
const scale = 1 / flowerSizeScale(d["Ambitious Climate Policy"]);
return "translate(" + -20 + "," + -20 + ")scale(" + scale + ")";
});
// position center of flower
const legendCircles = legend
.selectAll("circle")
.data(function(d) {
const colour = circleColourScale(d["Left-Wing Government"]);
console.log(colour);
return [{ colour: colour, x_axis: 75, y_axis: 75, radius: 20 }];
})
.enter()
.append("circle");
const legendCircleAttributes = legendCircles
.attr("cx", function(d) {
return d.x_axis;
})
.attr("cy", function(d) {
return d.y_axis;
})
.attr("r", function(d) {
return d.radius;
})
.attr("stroke", "#000")
.attr("stroke-width", 2)
.attr("fill", d => d.colour);
});
</script>
<svg></svg>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment