Public
Edited
Sep 21, 2023
3 forks
19 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
minHours = d3.min(subset, d => d.hoursPerDayCombined);
Insert cell
maxHours = d3.max(subset, d => d.hoursPerDayCombined);
Insert cell
domain = d3.range(minHours, maxHours, (maxHours - minHours) / 7)
Insert cell
countriesGeo = FileAttachment("countries.geojson").json()
Insert cell
Insert cell
Insert cell
Insert cell
mutable clickedSubcategory = "Food preparation"
Insert cell
mutable hoveredCategory = null
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
height = 700 - margin.top - margin.bottom
Insert cell
width = 700 - margin.left - margin.right
Insert cell
margin = ({top: 20, right: 20, bottom: 50, left: 50})
Insert cell
ellipse = d3
.range(100)
.map(i => [
(width * (1 + 0.99 * Math.cos((i / 50) * Math.PI))) / 2,
(height * (1 + 0.99 * Math.sin((i / 50) * Math.PI))) / 2
])
Insert cell
Insert cell
d3 = require("d3@5", "d3-weighted-voronoi", "d3-voronoi-map", "d3-voronoi-treemap", 'seedrandom@2.4.3/seedrandom.min.js')
Insert cell
flubber = require("flubber@0.4")
Insert cell
Insert cell
// Define a custom tick format function to convert decimal hours to minutes
function customTickFormat(value) {
const hours = Math.floor(value);
const minutes = Math.round((value - hours) * 60);
return `${hours}:${String(minutes).padStart(2, '0')}`;
}
Insert cell
function decimalToHoursMinutes(decimal) {
// Calculate the hours by rounding down the decimal number
const hours = Math.floor(decimal);

// Calculate the remaining minutes by multiplying the decimal part by 60
const minutes = Math.round((decimal - hours) * 60);

let timeString = '';

// Add hours to the output only if it's greater than 0
if (hours > 0) {
timeString += `${hours} hr${hours > 1 ? 's' : ''}`;
}

// Add minutes to the output only if it's greater than 0
if (minutes > 0) {
if (timeString) {
timeString += ' ';
}
timeString += `${minutes} min`;
}

// If neither hours nor minutes are greater than 0, return "0 min"
if (!timeString) {
timeString = "0 min";
}

return timeString;
}
Insert cell
function getCountryNameByISO3(code) {
// Assuming tt_countries is an array of country objects
// with 'country_name' and 'country_iso3' fields
const country = tt_countries.find((item) => item.country_iso3 === code);

if (country) {
return country.country_name;
} else {
return "Country not found"; // You can customize the error message
}
}


Insert cell
Insert cell
tt_ghd_countries = d3.csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-09-12/all_countries.csv", d3.autoType)
Insert cell
tt_countries = d3.csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-09-12/country_regions.csv", d3.autoType)
Insert cell
Insert cell
selectedIsoCode = tt_countries.filter(d => {return d.country_name === selectedCountry})[0].country_iso3
Insert cell
tt_country = tt_ghd_countries.filter(d => {return d.country_iso3 === selectedIsoCode})
Insert cell
Insert cell
// function taken directly from Will Chase, modified to fit categories instead of regions
function colorHierarchy(hierarchy) {
if(hierarchy.depth === 0) {
hierarchy.color = 'black';
} else if(hierarchy.depth === 1){
hierarchy.color = categoryColor(hierarchy.data.key);
} else {
hierarchy.color = hierarchy.parent.color;
}
if(hierarchy.children) {
hierarchy.children.forEach( child => colorHierarchy(child))
}
}
Insert cell
categoryColor = function(category) {
var colors = {
"Food provision": "#48EB70",
"Nonfood provision": "#FF9D13",
"Technosphere modification": "#DCDCDC",
"Maintenance of surroundings": "#F95738",
"Somatic maintenance": "#EBCD49",
"Deliberate neural restructuring": "#4DEAFF",
"Organization" : "#00BFB2",
"Experience oriented" : "#7F2FFF"
};
return colors[category];
}
Insert cell
Insert cell
category_hierarchy = d3.hierarchy(country_nested, d => d.values)
.sum(d => d.hoursPerDayCombined)
Insert cell
country_nested = {
let country_nest = d3.nest()
.key(d => d.Category)
.entries(tt_country)
return {key: "country_nest", values: country_nest}
}
Insert cell
countries = [...new Set(tt_countries.map(f => f.country_name))].sort()
Insert cell
subcategories = [...new Set(tt_ghd_countries.map(f => f.Subcategory))]
Insert cell
categories = [...new Set(query.map(f => f.category))]
Insert cell
y_axis_list = ['Title', ...categories];
Insert cell
subset = tt_ghd_countries.filter(d => d.Subcategory === selectedSubcategory)
Insert cell
tt_ghd_countries
SELECT
Category as category,
SUM(CASE WHEN country_group = 'USA' THEN hrs ELSE 0 END) AS country_stat,
AVG(CASE WHEN country_group = 'World Avg' THEN hrs ELSE 0 END) AS global_stat
FROM (
SELECT
country_iso3
,CASE WHEN country_iso3 = ${selectedIsoCode} THEN 'USA' ELSE 'World Avg' END AS country_group,
Category,
SUM(hoursPerDayCombined) as hrs
FROM tt_ghd_countries
GROUP BY 1,2,3
) a
GROUP BY Category
ORDER BY 2 desc;

Insert cell
Insert cell
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