Public
Edited
Sep 13, 2023
Insert cell
Insert cell
Plot.plot({
width,
projection: "equal-earth",
marks: [
// Plot.graticule(),
Plot.geo(land, { fill: "currentColor" }),
Plot.geo(peersGeoJson, { fill: "red" }),
Plot.tip(
peersGeoJson,
Plot.pointer(
Plot.centroid({ title: (d) => generatePeerText(d.properties) })
)
)
]
})
Insert cell
generatePeerText = (peer) =>
`AS${peer.asn} \n${peer.ip} \n${peer.locodeMatch.nameWithoutDiacritics}, ${peer.locodeMatch.iso2} \nRRC${peer.rrc}`
Insert cell
peersWithLocodeData = peers.data.map((peer) => {
let locodeMatch = cities
.filter((city) => city.latitude && city.longitude)
.filter(
(city) => city.iso2 === peer.country && city.locode === peer.city
)[0];

return { ...peer, locodeMatch };
})
Insert cell
/*

From https://unece.org/trade/cefact/UNLOCODE-Download:

Geographical coordinates
6. A column for geographical coordinates (latitude/longitude) was introduced in UN/LOCODE 2002-1. Data is being added in this column as it becomes available to the Secretariat. In order to avoid unnecessary use of non-standard characters and space, the following standard presentation is used:

ddmmN dddmmW, ddmmS dddmmE, etc.,
*/

NSEWtoLatLng = (s) => {
let dd, mm;
let last = s.slice(-1);
if (last === "N" || last === "S") [dd, mm] = [s.slice(0, 2), s.slice(2, 4)];
if (last === "W" || last === "E") [dd, mm] = [s.slice(0, 3), s.slice(3, 5)];

[dd, mm] = [parseInt(dd), parseInt(mm)];

// negatives
if (last === "S" || last === "W") [dd, mm] = [dd * -1, mm * -1];

return dd + mm / 60;
}
Insert cell
peersGeoJson = peersWithLocodeData
.filter((peer) => peer.locodeMatch)
.map((peer) => {
return {
type: "Feature",
geometry: {
type: "Point",
coordinates: [
NSEWtoLatLng(peer.locodeMatch.longitude),
NSEWtoLatLng(peer.locodeMatch.latitude)
]
},
properties: {
...peer
}
};
})
Insert cell
Insert cell
peersWithLocodeData
Type Table, then Shift-Enter. Ctrl-space for more options.

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