Public
Edited
May 31
Insert cell
Insert cell
d3 = require("d3@6");
Insert cell
Insert cell
// The years we wish to make visualizations for
years = ["1920", "1960", "2000"]
Insert cell
// Colors of the points in the scatter plots
colors = [ { id: "normal", color: "#000000"},
{ id: "host", color: "#4287f5"},
{ id: "non-host", color: "#DEDEDE"},
{ id: "average", color: "#000000"}]
Insert cell
function color(id){
return colors.find( d => d.id == id ).color
}
Insert cell
// Order of the dot types in the host scatter plot
placementHierarchy = [ { id: "host", placement: 2},
{ id: "non-host", placement: 0},
{ id: "average", placement: 1}]
Insert cell
function placement(id){
return placementHierarchy.find( d => d.id == id ).placement
}
Insert cell
Insert cell
rawOlympicData = d3.csvParse(await FileAttachment("ALL_MEDALISTS_modified@3.csv").text(), d3.autoType);
Insert cell
rawGdpData = d3.csvParse(await FileAttachment("GDP_Data_Year_1_To_2008_modified@2.csv").text(), d3.autoType);
Insert cell
rawPopulationData = d3.csvParse(await FileAttachment("Population_Data_Year_1_To_2008_modified@2.csv").text(), d3.autoType);
Insert cell
rawNocData = d3.csvParse(await FileAttachment("NOC_CODES_modified.csv").text(), d3.autoType);
Insert cell
Insert cell
function processOlympicData()
{
let formattedData = [];
const allYears = {};

rawOlympicData.forEach(d => {
if(!(d["Edition"] in allYears))
{
const newYear = {
year: d["Edition"],
host: d["HostNOC"],
countryMedals: {}
}
allYears[d["Edition"]] = newYear;
}
if(d["NOC"] in allYears[d["Edition"]].countryMedals)
{
allYears[d["Edition"]].countryMedals[d["NOC"]].medals =
allYears[d["Edition"]].countryMedals[d["NOC"]].medals + 1;
}
else if ( Object.values(d) != null &&
rawNocData.some(c => c["NOC"] == d["NOC"]) )
{
const newCountryMedal = {
NOC: d["NOC"],
medals: 1
}
allYears[d["Edition"]].countryMedals[d["NOC"]] = newCountryMedal;
}
})
Object.keys(allYears).forEach(d => {
formattedData.push(allYears[d]);
})
return formattedData;
}
Insert cell
olympicData = processOlympicData();
Insert cell
function processPopulationData()
{
let populationData = [];
years.forEach(year => {
let data = [];
let countryMedals = olympicData.find( c => c.year == year ).countryMedals;

rawPopulationData.forEach(d => {
if( d.NOC in countryMedals )
{
let population = d[year];
let medals = countryMedals[d.NOC].medals;
if( population != null && medals != null )
{
const dataPoint = {
NOC: d.NOC,
population: Number(population),
medals: medals
}
data.push(dataPoint);
}
}
})

const dataPoint = {
year: year,
data: data
}
populationData.push(dataPoint);
})
return populationData;
}
Insert cell
populationData = processPopulationData();
Insert cell
function processGdpData()
{
let gdpData = [];
years.forEach(year => {
let data = [];
let countryMedals = olympicData.find( c => c.year == year ).countryMedals;

rawGdpData.forEach(d => {
if( d.NOC in countryMedals )
{
let gdp = d[year];
let medals = countryMedals[d.NOC].medals;
if( gdp != null && medals != null )
{
const dataPoint = {
NOC: d.NOC,
gdp: Number(gdp),
medals: medals
}
data.push(dataPoint);
}
}
})

const dataPoint = {
year: year,
data: data
}
gdpData.push(dataPoint);
})
return gdpData;
}
Insert cell
gdpData = processGdpData();
Insert cell
function processHostData()
{
let hostData = [];
years.forEach(year => {
let data = [];
let countryMedals = olympicData.find( c => c.year == year ).countryMedals;

rawOlympicData.forEach(d => {
if( d.NOC in countryMedals )
{
let host = countryMedals[d.NOC].NOC == olympicData.find( c => c.year == year ).host
? "host" : "non-host";
let medals = countryMedals[d.NOC].medals;
if( host != null && medals != null )
{
const dataPoint = {
NOC: d.NOC,
host: host,
medals: medals
}
data.push(dataPoint);
}
}
})

const dataPoint = {
year: year,
data: data
}
hostData.push(dataPoint);
})
return hostData;
}
Insert cell
hostData = processHostData(olympicData);
Insert cell
Insert cell
function makeScatterPlot(data, factor, year){
// measurements
const margin = ({top: 100, right: 200, bottom: 40, left: 40});
const height = 450;
const width = 1300;

// Create the svg
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

// Create the title
svg.append("text")
.attr("text-anchor", "middle")
.attr("x", (margin.left + width - margin.right) / 2)
.attr("y", margin.top / 2)
.attr("font-weight", "bold")
.style("font-size", "25px")
.text(factor + " vs. medals won - " + year);
// Create the x axis label
svg.append("text")
.attr("text-anchor", "middle")
.attr("x", (margin.left + width - margin.right) / 2)
.attr("y", height - 5)
.attr("font-weight", "bold")
.style("font-size", "15px")
.text(factor);

// Create the y axis label
svg.append("text")
.attr("text-anchor", "start")
.attr("x", margin.left - 20)
.attr("y", margin.top - 15)
.attr("font-weight", "bold")
.style("font-size", "15px")
.text("medals won");
// Create the x axis
const x = factor == "host" ?
d3.scaleBand()
.domain(data.map(d => d[factor]))
: d3.scaleLog()
.domain([d3.min(data, d => d[factor]), d3.max(data, d => d[factor])]);
x.range([margin.left, width - margin.right])
const xAxis = g => g
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x))
svg.append("g")
.call(xAxis)

// Create the y axis
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.medals)])
.rangeRound([height - margin.bottom, margin.top]);
const yAxis = g => g
.attr("transform", "translate(" + (margin.left) + ",0)")
.call(d3.axisLeft(y))
svg.append("g")
.call(yAxis)

// Create the dots
svg.append("g")
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cx", (d) => factor == "host" ? x(d[factor]) + x.bandwidth()/2: x(d[factor]))
.attr("cy", (d) => y(d.medals))
.attr("r", (d) => 5)
.style("fill", "black");
return svg.node();
}
Insert cell
populationPlot2000 = makeScatterPlot(populationData.find( c => c.year == years[2] ).data, "population", years[2]);
Insert cell
gdpPlot2000 = makeScatterPlot(gdpData.find( c => c.year == years[2] ).data, "gdp", years[2]);
Insert cell
hostPlot1920 = makeScatterPlot(hostData.find( c => c.year == years[0] ).data, "host", years[0]);
Insert cell
hostPlot1960 = makeScatterPlot(hostData.find( c => c.year == years[1] ).data, "host", years[1]);
Insert cell
hostPlot2000 = makeScatterPlot(hostData.find( c => c.year == years[2] ).data, "host", years[2]);
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more