|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
svg { background-color: #ffffff; } |
|
.label { font-size: 18pt; font-family:Helvetica; } |
|
</style> |
|
</head> |
|
<body> |
|
<script> |
|
// variables |
|
let w = 960; |
|
let h = 500; |
|
let margin = { top: 20, right: 20, left: 150, bottom: 120 }; |
|
let innerWidth = w - margin.right - margin.left; |
|
let innerHeight = h - margin.top - margin.bottom; |
|
|
|
let happy = []; |
|
let fieldStats = []; |
|
let xLinear; |
|
let yLinear = d3.scaleLinear(); |
|
let svg = d3.select("body").append("svg") |
|
.attr("width", w) |
|
.attr("height", h); |
|
|
|
// Create dynamic scales based on columns passed |
|
const createScales=(xField,yField)=>{ |
|
xLinear = d3.scaleLinear() |
|
.domain([d3.min(happy,(d,i)=>{ return d[xField]; }), d3.max(happy,(d,i)=>{ return d[xField]; })]) |
|
.range([0 + margin.left, w - margin.right]) |
|
.nice(); |
|
yLinear = d3.scaleLinear() |
|
.domain([0,d3.max(happy,(d,i)=>{ return d[yField]; })]) |
|
.range([innerHeight,0 + margin.bottom]) |
|
.nice(); |
|
} |
|
|
|
// Create dynamic axis based on columns passed |
|
const createAxis=(xField,yField)=>{ |
|
let xAxis = d3.svg.axis(); |
|
} |
|
|
|
// Create Scatter plot based on columns passed (happy) |
|
const createScatterPlot=(xField,yField,rField)=>{ |
|
svg.selectAll("circle") |
|
.data(happy) |
|
.enter() |
|
.append("circle") |
|
.attr("cx", (d,i)=>{ return xLinear(d[xField]); }) |
|
.attr("cy", (d,i)=>{ return yLinear(d[yField]); }) |
|
.attr("r", (d,i)=>{ return d[rField] * 10; }); |
|
|
|
svg.append("g") |
|
.attr("transform", "translate(0," + innerHeight + ")") |
|
.call(d3.axisBottom(xLinear)); |
|
|
|
svg.append("text") |
|
.attr("class","label") |
|
.attr("y", 425) |
|
.attr("x", w /2) |
|
.style("text-anchor", "middle") |
|
.text("Happiness Ranking"); |
|
|
|
svg.append("g") |
|
.attr("transform", "translate(" + 150 + "," + 0 + ")") |
|
.call(d3.axisLeft(yLinear)); |
|
|
|
svg.append("text") |
|
.attr("class","label") |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", 100) |
|
.attr("x", -(h / 2)) |
|
.style("text-anchor", "middle") |
|
.text("GDP Per Capita"); |
|
|
|
svg.append("text") |
|
.attr("class","label") |
|
.attr("y", 50) |
|
.attr("x", w /2) |
|
.style("text-anchor", "middle") |
|
.text("World Happiness Ranking"); |
|
|
|
} |
|
|
|
// Convert header to JSON friendly header (Columns) |
|
const processHappy=(d)=>{ |
|
return { |
|
country: d["Country"], |
|
happinessRank: +d["Happiness_Rank"], |
|
happinessScore: +d["Happiness_Score"], |
|
whiskerHigh: +d["Whisker_high"], |
|
whiskerLow: +d["Whisker_low"], |
|
gdpPerCapita: +d["Economy__GDP_per_Capita_"], |
|
family: +d["Family"], |
|
lifeExpectancy: +d["Health__Life_Expectancy_"], |
|
freedom: +d["Freedom"], |
|
generosity: +d["Generosity"], |
|
governmentCorruption: +d["Trust__Government_Corruption_"], |
|
dystopiaResidual: +d["Dystopia_Residual"] |
|
}; |
|
} |
|
|
|
// Load world happiness data |
|
const happyFile=()=>{ |
|
d3.csv("data1.csv",processHappy,data=>{ |
|
happy = data; |
|
|
|
// For each column calculate basic statistics |
|
fieldStats.push(fieldProfile("happinessRank")); |
|
fieldStats.push(fieldProfile("happinessScore")); |
|
fieldStats.push(fieldProfile("whiskerHigh")); |
|
fieldStats.push(fieldProfile("whiskerLow")); |
|
fieldStats.push(fieldProfile("gdpPerCapita")); |
|
fieldStats.push(fieldProfile("family")); |
|
fieldStats.push(fieldProfile("lifeExpectancy")); |
|
fieldStats.push(fieldProfile("freedom")); |
|
fieldStats.push(fieldProfile("generosity")); |
|
fieldStats.push(fieldProfile("governmentCorruption")); |
|
fieldStats.push(fieldProfile("dystopiaResidual")); |
|
|
|
// Write out all the statistics |
|
fieldStats.forEach((row,index)=>{ |
|
console.log(JSON.stringify(row)); |
|
}); |
|
// World Happyiness Rank |
|
createScales("happinessScore","gdpPerCapita"); |
|
createScatterPlot("happinessScore","gdpPerCapita","lifeExpectancy"); |
|
}); |
|
}; |
|
|
|
// Calculate basic statistics on a field |
|
const fieldProfile=(fieldname)=>{ |
|
const avg = d3.nest().rollup((v)=>{ return d3.mean(v, (d)=>{ return d[fieldname]; }); }).entries(happy); |
|
const med = d3.nest().rollup((v)=>{ return d3.median(v, (d)=>{ return d[fieldname]; }); }).entries(happy); |
|
const min = d3.nest().rollup((v)=>{ return d3.min(v, (d)=>{ return d[fieldname]; }); }).entries(happy); |
|
const max = d3.nest().rollup((v)=>{ return d3.max(v, (d)=>{ return d[fieldname]; }); }).entries(happy); |
|
|
|
happy.sort((a,b)=>{ return a[fieldname] - b[fieldname]; }); |
|
const p25 = Math.round(happy.length * .25); |
|
const v25 = happy[p25][fieldname]; |
|
const v75 = happy[happy.length - p25]; |
|
|
|
const stats = {}; |
|
stats["fieldname"] = fieldname; |
|
stats["average"] = avg; |
|
stats["median"] = med; |
|
stats["min"] = min; |
|
stats["max"] = max; |
|
stats["p25"] = v25; |
|
stats["p75"] = v75[fieldname]; |
|
|
|
return stats; |
|
} |
|
|
|
document.addEventListener("DOMContentLoaded", (event)=>{ |
|
// World Happyiness Rank |
|
happyFile(); |
|
}); |
|
</script> |
|
</body> |