Public
Edited
Apr 26
2 forks
Insert cell
Insert cell
Insert cell
happiness_data@7.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
happiness_data = FileAttachment("happiness_data@7.csv").csv({typed: true});
Insert cell
const csvNameToMapName = {
"Mauritania": "Mauritania",
"Bolivia": "Bolivia",
"Venezuela": "Venezuela",
"Portugal": "Portugal",
"Myanmar": "Myanmar",
"Kazakhstan": "Kazakhstan",
"Croatia": "Croatia",
"Panama": "Panama",
"Mexico": "Mexico",
"China": "China",
"Jordan": "Jordan",
"Estonia": "Estonia",
"Bangladesh": "Bangladesh",
"Mauritius": "Mauritius",
"Ireland": "Ireland",
"Gabon": "Gabon",
"Slovenia": "Slovenia",
"Ukraine": "Ukraine",
"Botswana": "Botswana",
"El Salvador": "El Salvador",
"Bulgaria": "Bulgaria",
"Georgia": "Georgia",
"Greece": "Greece",
"Jamaica": "Jamaica",
"Madagascar": "Madagascar",
"Bahrain": "Bahrain",
"Afghanistan": "Afghanistan",
"Ecuador": "Ecuador",
"Malaysia": "Malaysia",
"Pakistan": "Pakistan",
"Moldova": "Moldova",
"Egypt": "Egypt",
"Saudi Arabia": "Saudi Arabia",
"Argentina": "Argentina",
"Ghana": "Ghana",
"Malta": "Malta",
"Cyprus": "Cyprus",
"Albania": "Albania",
"Russia": "Russian Federation",
"Sri Lanka": "Sri Lanka",
"Hungary": "Hungary",
"Comoros": "Comoros",
"Luxembourg": "Luxembourg",
"Mozambique": "Mozambique",
"Finland": "Finland",
"Sierra Leone": "Sierra Leone",
"Poland": "Poland",
"Algeria": "Algeria",
"Bosnia and Herzegovina": "Bosnia and Herzegovina",
"Austria": "Austria",
"Gambia": "Gambia",
"Colombia": "Colombia",
"Uzbekistan": "Uzbekistan",
"Australia": "Australia",
"Italy": "Italy",
"Spain": "Spain",
"Philippines": "Philippines",
"Kyrgyzstan": "Kyrgyzstan",
"Honduras": "Honduras",
"Belgium": "Belgium",
"Lebanon": "Lebanon",
"Burkina Faso": "Burkina Faso",
"Canada": "Canada",
"Peru": "Peru",
"Iceland": "Iceland",
"Morocco": "Morocco",
"Iran": "Iran",
"Romania": "Romania",
"Costa Rica": "Costa Rica",
"Latvia": "Latvia",
"Namibia": "Namibia",
"India": "India",
"Liberia": "Liberia",
"France": "France",
"New Zealand": "New Zealand",
"Tunisia": "Tunisia",
"Brazil": "Brazil",
"Chad": "Chad",
"Benin": "Benin",
"Indonesia": "Indonesia",
"Armenia": "Armenia",
"Niger": "Niger",
"United Arab Emirates": "United Arab Emirates",
"Uganda": "Uganda",
"Cambodia": "Cambodia",
"Israel": "Israel",
"Malawi": "Malawi",
"Zimbabwe": "Zimbabwe",
"Thailand": "Thailand",
"Denmark": "Denmark",
"Slovakia": "Slovakia",
"Mongolia": "Mongolia",
"South Korea": "South Korea",
"Singapore": "Singapore",
"Laos": "Laos",
"Cameroon": "Cameroon",
"Chile": "Chile",
"Zambia": "Zambia",
"Montenegro": "Montenegro",
"Dominican Republic": "Dominican Republic",
"Uruguay": "Uruguay",
"Iraq": "Iraq",
"Togo": "Togo",
"Sweden": "Sweden",
"Kenya": "Kenya",
"Netherlands": "Netherlands",
"Guatemala": "Guatemala",
"Switzerland": "Switzerland",
"Japan": "Japan",
"South Africa": "South Africa",
"Nepal": "Nepal",
"Paraguay": "Paraguay",
"Vietnam": "Vietnam",
"Germany": "Germany",
"Mali": "Mali",
"Nicaragua": "Nicaragua",
"Guinea": "Guinea",
"Tajikistan": "Tajikistan",
"Senegal": "Senegal",
"Ethiopia": "Ethiopia",
"Nigeria": "Nigeria",
"Norway": "Norway",
"Lithuania": "Lithuania",
"United Kingdom": "United Kingdom",
"United States": "United States of America",
"North Korea": "North Korea",
"Tanzania": "Tanzania",
"Czech Republic": "Czech Republic",
"Syria": "Syria",
"Ivory Coast": "Ivory Coast",
"Republic of the Congo": "Republic of the Congo",
"Democratic Republic of the Congo": "Democratic Republic of the Congo",
"Palestinian Territories": "Palestine",
"Hong Kong S.A.R. of China": "Hong Kong",
"Taiwan Province of China": "Taiwan",
"Somaliland region": "Somaliland",
"Kosovo": "Kosovo",
"Swaziland": "Eswatini",
"Burma": "Myanmar",
"North Macedonia": "North Macedonia"
};

// 创建地图的颜色比例
const color = d3.scaleLinear()
.domain([3, 8])
.range(["lightgreen", "darkgreen"]);

// 设置地图的投影
const projection = d3.geoMercator().scale(150).translate([width / 2, height / 1.5]);
const path = d3.geoPath().projection(projection);

// 获取世界地图数据
const world = topojson.feature(worldMap, worldMap.objects.countries).features;

// 渲染地图
svg = d3.select("svg")
.attr("width", 960)
.attr("height", 500);

// 加载数据
{
const happinessMap = {};
happiness_data.forEach(d => {
const csvName = d.Country.trim();
const mapName = csvNameToMapName[csvName] || csvName;
happinessMap[mapName] = +d["Happiness score"];
});

svg.selectAll("path")
.data(world)
.join("path")
.attr("d", path)
.attr("fill", d => {
const mapCountry = d.properties.name;
const score = happinessMap[mapCountry];
return score && !isNaN(score) ? color(score) : "#ccc";
})
.attr("stroke", "#fff")
.attr("stroke-width", 0.5)
.on("click", (event, d) => {
const mapCountry = d.properties.name;
const csvRow = happiness_data.find(r => {
const csvCountry = r.Country.trim();
const mapName = csvNameToMapName[csvCountry] || csvCountry;
return mapName === mapCountry;
});
if (csvRow) {
drawLineChart(csvRow, mapCountry);
}
})
.append("title")
.text(d => {
const mapCountry = d.properties.name;
const score = happinessMap[mapCountry];
return score ? `${mapCountry}: ${score}` : `${mapCountry}: no data`;
});
}

// 绘制折线图
function drawLineChart(countryData, countryName) {
d3.select("#linechart").selectAll("*").remove();

const margin = { top: 50, right: 30, bottom: 50, left: 60 },
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;

const svg = d3.select("#linechart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

const indicators = [
"Logged GDP per capita",
"Social support",
"Healthy life expectancy",
"Freedom to make life choices",
"Perceptions of corruption",
"Education",
"LivingConditions",
"SafetySecurity"
];

const data = indicators.map(indicator => ({ indicator: indicator, value: +countryData[indicator] }));

const x = d3.scalePoint()
.domain(indicators)
.range([0, width])
.padding(0.5);

const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value) * 1.1])
.range([height, 0]);

svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "rotate(20)")
.style("text-anchor", "start");

svg.append("g")
.call(d3.axisLeft(y));

svg.append("g")
.attr("class", "grid")
.call(d3.axisLeft(y).tickSize(-width).tickFormat(""));

const line = d3.line()
.x(d => x(d.indicator))
.y(d => y(d.value));

svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2)
.attr("d", line);

svg.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => x(d.indicator))
.attr("cy", d => y(d.value))
.attr("r", 4)
.attr("fill", "steelblue");

svg.append("text")
.attr("x", width / 2)
.attr("y", -20)
.attr("text-anchor", "middle")
.style("font-size", "18px")
.text(`Indicators for ${countryName}`);

svg.append("text")
.attr("text-anchor", "middle")
.attr("x", width / 2)
.attr("y", height + 40)
.text("Indicator Name");

svg.append("text")
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.attr("y", -50)
.attr("x", -height / 2)
.text("Indicator Value");
}
Insert cell
Insert cell
Insert cell
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