Public
Edited
Mar 1, 2023
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// From The Global Carbon Project's fossil CO2 emissions dataset
// Last updated October 17, 2022
// via https://zenodo.org/record/7215364#.Y68UpezMJqs
gcp = FileAttachment("GCB2022v27_MtCO2_flat.csv").csv()
Insert cell
// From the U.S. Energy Information Administration's International Energy Outlook 2021
// via https://www.eia.gov/outlooks/aeo/data/browser/#/?id=10-IEO2021
eia = FileAttachment("World_carbon_dioxide_emissions_by_region.csv").text()
Insert cell
// From the United Nations, Department of Economic and Social Affairs, Population Division (2022). World Population Prospects 2022, Online Edition.
// via https://population.un.org/wpp/Download/Standard/Population/
un = FileAttachment("WPP2022_Demographic_Indicators_Medium.csv").csv({ typed: true })
Insert cell
// Scraped from https://unfccc.int/process/parties-non-party-stakeholders/parties-convention-and-observer-states
// Site was last updated Oct. 25, 2022
unfccc = FileAttachment("unfccc-parties@6.json").json()
Insert cell
// From the World Bank, data through 2021
// via https://data.worldbank.org/indicator/NY.GDP.MKTP.CD
worldbank = FileAttachment("API_NY.GDP.MKTP.CD_DS2_en_csv_v2_4770391.csv").text()
Insert cell
// Email from EIA spokesman Chris Higginbotham:
// OECD Europe = Austria, Belgium, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Iceland, Ireland, Italy, Latvia, Lithuania Luxembourg, Netherlands, Norway, Poland, Portugal, Slovakia, Slovenia, Spain, Sweden, Switzerland, Turkey, and United Kingdom. (Note: Israel is included in OECD Europe for statistical reporting purposes.)
// Those countries' ISO-3 codes are below:
oecdEurope = ["AUT", "BEL", "CZE", "DNK", "EST", "FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ISR", "ITA", "LVA", "LTU", "LUX", "NLD", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE", "CHE", "TUR", "GBR"]
Insert cell
Insert cell
// Parse the Global Carbon Project data, removing unused columns and calculating cumulative sums
gcpParsed = {
// column index, simplified column name, column formatter
const cols = [
[0, "entity", d => d],
[1, "code", d => d],
[2, "year", d => +d],
[3, "annual", d => +d * 1e6]
];

// Simplify column names and coerce data types
const parsed = gcp
.map(d => {
const o = {};
let sum = 0;
cols.forEach(([i, c, f]) => {
o[c] = f(d[gcp.columns[i]]);
});
if (o.entity === "USA") o.entity = "United States"
return o;
});

// Calculate cumulative sums
return d3
.groups(parsed, d => d.entity)
.map(([entity, entries]) => {
const cumsum = d3.cumsum(entries, d => d.annual);
entries.forEach((d, i) => (d.cumulative = cumsum[i], d));
return entries;
})
.flat();
}
Insert cell
// Add Europe as an entity into the Global Carbon Project data
gcpWithEurope = {
return [
...gcpParsed.filter(d => !oecdEurope.includes(d.code)),
...d3
.range(...d3.extent(gcpParsed, d => d.year).map((d, i) => i ? d + 1 : d))
.map(year => {
const filtered = gcpParsed.filter(d => d.year === year && oecdEurope.includes(d.code));
const annual = d3.sum(filtered, d => d.annual);
const cumulative = d3.sum(filtered, d => d.cumulative);
return {
entity: "Europe",
code: "EUR",
year,
annual,
cumulative
}
})
]
}
Insert cell
// Parse the EIA's CSV and transform it from wide to narrow
eiaParsed = {
const rows = eia.split("\n").slice(4);
const header = rows[0].replace(`""`, "entity");
const columns = header.split(",").map(c => c.replaceAll('"', ""));
const years = columns.filter(d => !isNaN(+d));
const countries = ["United States", "Canada", "Japan", "South Korea", "Russia", "China", "India", "Brazil", "Europe"];
const wide = rows
.slice(1)
.map(d => {
const o = {};
d.split(",").forEach((v, i) => {
o[columns[i]] = v;
});
return o;
});

return d3
.cross(wide, years)
.map(([d, year]) => ({
entity: d.entity === "OECD Europe" ? "Europe" : d.entity,
year: +year,
annual: +d[year] * 1e6
}))
.filter(d => countries.includes(d.entity));
}
Insert cell
// Calculate populations for relevant entities between 1950-2101
unParsed = {
const C = ["United States of America", "Canada", "Japan", "Republic of Korea", "Russian Federation", "China", "India", "Brazil"];

const pops = un
.filter(d => d.LocTypeID === 4)
.map(d => ({
entity: d.Location,
code: d.ISO3_code,
year: d.Time,
pop: d.TPopulation1Jan * 1e3
}));
const countries = pops
.filter(d => C.includes(d.entity))
.map(d => {
d.pop = Math.round(d.pop)
d.entity =
d.entity === "United States of America" ? "United States" :
d.entity === "Republic of Korea" ? "South Korea" :
d.entity === "Russian Federation" ? "Russia" :
d.entity;
return d;
});
const europe = (() => {
const filtered = pops.filter(d => oecdEurope.includes(d.code))
return d3.range(1950, 2102).map(year => {
return {
entity: "Europe",
code: "EUR",
year,
pop: Math.round(d3.sum(filtered.filter(d => d.year === year), d => d.pop))
}
})
})();

return [
...countries,
...europe
];
}
Insert cell
// Parse the World Bank data, transforming it from wide to narrow
worldbankParsed = {
const wide = d3.csvParse(worldbank
.split("\n")
.filter((d, i) => i > 3)
.join("\n"));

const cols = Object.keys(wide[0]).filter(d => d);
const years = cols.filter(d => !isNaN(+d));

return d3
.cross(wide, years)
.map(([d, year]) => {
return {
entity: d["Country Name"],
code: d["Country Code"],
year: +year,
gdp: +d[year]
}
});
}
Insert cell
Insert cell
// Combine the datasets from the Global Carbon Project, the UN, and the EIA
emissions = d3
.groups(eiaParsed, d => d.entity)
.map(([entity, entries]) => {
const match = gcpWithEurope.filter(d => d.entity === entity)
return [...match, ...entries.filter(d => d.year > 2021)]
.map((d, i, e) => {
// Calculate cumulative sums for projected years
if (d.cumulative == null && !isFinite(d.cumulative)){
const prev = e[i - 1];
d.code = match[0].code;
d.cumulative = prev.cumulative + d.annual;
}

// Add populations for available years
const m = unParsed.find(f => d.year === f.year && d.entity === f.entity);
d.pop = m?.pop || null;
d.annual_percap = d.pop ? d.annual / d.pop : null;
return d;
})
})
.flat()
.filter(d => d.cumulative);
Insert cell
// Combine the datasets from the UNFCCC, the World Bank, and the Global Carbon Project
// There are 198 parties to the UNFCCC, but only 182 countries will be shown
// The World Bank does not have 2021 GDP data for 14 UNFCCC parties: Cuba, Cook Islands, Eritrea, European Union, Holy See, Kuwait, Liechtenstein, Niue, North Korea, South Sudan, Syria, Turkmenistan, Venezuela, Yemen
// The Global Carbon Project does not have emissions data for Monaco and San Marino
parties = unfccc
.map(d => {
const worldbankMatch = worldbankParsed.find(f => f.code === d.iso && f.year === 2021)
if (!worldbankMatch) return null;
const o = Object.assign({}, worldbankMatch);

const gcpMatch = gcp.find(f => f["ISO 3166-1 alpha-3"] === o.code && f.Year === "2021")
if (!gcpMatch) return null;
o.co2 = +gcpMatch.Total * 1e6;

const unMatch = un.find(f => f.ISO3_code === o.code && f.Time === 2021)
o.pop = unMatch.TPopulation1Jan * 1e3;

o.gdp_percap = o.gdp / o.pop;
o.co2_percap = o.co2 / o.pop;
o.type = d.type;

return o;
})
.filter(d => d && d.gdp);
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more