Public
Edited
Jan 27, 2023
1 star
Insert cell
Insert cell
Insert cell
viewof yScaleButton = Inputs.radio(["log", "linear"], {label: "Y scale", value: 'log'})
Insert cell
viewof xScaleButton = Inputs.radio(["log", "linear"], {label: "X scale", value: 'log'})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof stroke = slider({
min: 1,
max: 20,
step: 0.01,
value: 3,
format: ",",
description:
"Stroke width"
})
Insert cell
colorScale.domain()
Insert cell
Insert cell
colorVal = 'ad_press_eq'
Insert cell
allDistances = {
let nodes = data[r1]
worldMap.select("#piecharts").remove()
worldMap.select("#land")
// worldMap.select("#land").remove()
// .style("fill", "#d8d8d8")
// // .style("stroke-width", 0.5)
// // .style("stroke", "#f4f4f4");
let adjSize = size *2;
if (dorling) {
const simulation = d3
.forceSimulation(nodes)
.force(
"x",
d3.forceX((d) => mapProjection([parseFloat(d[baseX]), parseFloat(d[baseY])])[0])
)
.force(
"y",
d3.forceY((d) => mapProjection([parseFloat(d[baseX]), parseFloat(d[baseY])])[1])
)
.force(
"collide",
d3.forceCollide(size+2).strength(repulsionFactor)
)
const nodeG = worldMap.append("g")
.attr("id", "piecharts")
.attr("stroke", "white")
.attr("stroke-width", 0.5)
.selectAll("g")
.data(nodes)
.join("g")
.call(drag(simulation))
nodeG.append("g")
.each(function(node) {
d3.select(this).append('g')
.append("rect")
.attr("stroke-width", 0.15)
.attr("stroke", "#8F5601")
.attr('fill', '#FFFCF6')
.attr("width", adjSize)
// .attr('x', -size)
// .attr('y', -size)
.attr("height", adjSize);

let linePoints = [{year: 2019, val: node[x]}, {year: 2050, val: node[y]}];
//let color = node[y] > node[x] ? 'green' : 'red';
// let color = colorScale(node['ad_press_eq']);
d3.select(this).append('path')
.datum(linePoints)
.attr("stroke", colorScale(node[colorVal]))
.attr("stroke-width", stroke)
.attr("stroke-opacity", 1)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);

})

simulation.on("tick", () => {
nodeG.attr("transform", d => `translate(${d.x}, ${d.y})`)
textG.attr("transform", d => `translate(${d.x}, ${d.y})`)
});
invalidation.then(() => simulation.stop());

const textG = worldMap.append("g")
.attr("id", "text-charts")
.selectAll("g")
.data(nodes)
.join("g")
.call(drag(simulation))
textG.append('g')
.attr('id', 'city-names')
.each(function(node) {
if (callouts.includes(node.city)) {
d3.select(this)
.append('text')
.text(node.city)
.attr('font-size', 6)
.attr('font-family', 'IBM Plex Sans')
.attr('stroke', 'none');
}
})
} else {
// Finalized unforced code

nodes.forEach(node => {
let coordinates = mapProjection([parseFloat(node[baseX]),parseFloat(node[baseY])]);
let x = coordinates[0];
let y = coordinates[1];
// let pieData = [];
// for (let i in categories[basePie]) {
// let name = categories[basePie][i]
// let value = parseFloat(node[name])
// pieData.push({name, value});
// }
// let arcs = pie(pieData);
// worldMap
// .append('g')
// .attr("id", "piecharts")
// .attr("transform", "translate(" + x + "," + y + ")")
// //.attr('stroke', pieStroke ? "white" : "none")
// .selectAll('path')
// .data(arcs)
// .join('path')
// .attr('fill',
// d => {
// return sectorColor(d.data.name)})
// .attr(
// 'd',
// d3
// .arc()
// .innerRadius(0)
// .outerRadius(() => radiusFunction(parseInt(node[radiusBase]))))
// .append('title')
// // title will not actually be visible
// .text(d => `${d.data.name}: ${d.data.value}`);
});
}

return worldMap.node();
}
Insert cell
colorScale(0)
Insert cell
colorScale = d3.scaleDivergingSqrt()
.domain([colorDomain[0], 0, colorDomain[1]])
.interpolator(d3.interpolateRgbBasis(["#005DAA","#E2D6CA", "#C5012D"]))
//.interpolator(t => d3.interpolateRdBu(1 - t))
//.interpolator(d3.interpolateRgbBasis(["#4C8EDA","#F5EFEF", "#FB6D07"]))
Insert cell
Insert cell
Insert cell
domainY = {
let nodes = data[r1];
let dom19 = nodes.map(row => row[x]);
let dom50 = nodes.map(row => row[y]);
let domain = dom50.concat(dom19);
console.log(dom50, dom19);
return d3.extent(domain);
}
Insert cell
line = d3.line()
.x(d => lineX(d.year))
.y(d => lineY(d.val));
Insert cell
lineX = d3.scaleLinear()
.domain(domainX)
.range([0, size*2]);
Insert cell
lineY = d3.scaleLog()
.domain(domainY)
.range([0, size*2]);
Insert cell
Object.keys(data[r1][0])
Insert cell
colorDomain = {
let nodes = data[r1];
let domain = nodes.map(row=>row[colorVal]);
return d3.extent(domain);
}
Insert cell
Insert cell
callouts = {
let df = data[r1];
df.sort(function(a, b){return a['ad_press_eq']-b['ad_press_eq']});
let first = df.slice(0, 3);
let last = df.slice(-3);
let dfN = first.concat(last);
return dfN.map(row => row.city);
}
Insert cell
Insert cell
Insert cell
slopeChart(topData)
Insert cell
topData
Insert cell
topData[0]
Insert cell
topData.filter(row=> row['name'] === 'London, GBR');
Insert cell
function slopeChart (data){
let y = r2 === 'rank' ? 'rank' : 'value';
let height = width*0.9;
return Plot.plot({
width: width,
height: height,
x: {type: "point", axis: "top", label: null},
y: {axis: null, inset: 20},
color: {
type: "ordinal",
domain: continents,
range: colors
},
marks: [
Plot.line(data, {x: "year", y: y, z: "name", strokeWidth: 4, stroke: "continent"}),
Plot.text(data, Plot.selectFirst({x: "year", y: y, z: "name", text: d => getText(d, y, data), textAnchor: "end", dx: -3, fill: "continent", fontSize: 16})),
Plot.text(data, Plot.selectLast({x: "year", y: y, z: "name", text: d => getText(d, y, data), textAnchor: "start", dx: 3, fill: "continent", fontSize: 16})),
]
})
}
Insert cell
function getText(d, type,data) {
if (type === 'rank' || type === 'value' || type === 'pagerank'){
return `${d.name} ${Math.abs(d.rank - 50)}`;
} else if (type === 'pagerank_order'){
return `${Math.abs(d.pagerank_order-50)} ${d.name}`;
}
}
Insert cell
cLegend = {
return legend({
color: d3.scaleOrdinal().domain(continents).range(colors),
title: "Legend",
width: width/1.5
})
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
continents = ["EU", "AS", "SA", "AF", "NA", "OC"]
Insert cell
baseX = 'city_lng'
Insert cell
baseY = 'city_lat'
Insert cell
x = 'ad_press_2050'
Insert cell
y = 'land_use_2019'
Insert cell
fill = "continent"
Insert cell
data = ({all, intl, dom})
Insert cell
sData[r1]
Insert cell
sData = ({'all': sAll, 'intl': sIntl, 'dom': sDom})
Insert cell
all = FileAttachment("all-ad-pressure@9.csv").csv({typed: true})
Insert cell
intl = FileAttachment("intl-ad-pressure@9.csv").csv({typed: true})
Insert cell
dom = FileAttachment("dom-ad-pressure@10.csv").csv({typed: true})
Insert cell
sAll = FileAttachment("s-all-ad-pressure@2.csv").csv({typed: true})
Insert cell
sIntl = FileAttachment("s-intl-ad-pressure@2.csv").csv({typed: true})
Insert cell
sDom = FileAttachment("s-dom-ad-pressure@2.csv").csv({typed: true})
Insert cell
Insert cell
import {addTooltips} from "@mkfreeman/plot-tooltip"
Insert cell
import {radio} from "@jashkenas/inputs"
Insert cell
import {mapProjection, activeColorScheme, worldMap} from "b3a0a78984d6df2e"
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
import {legend, swatches} from "@d3/color-legend"
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