Public
Edited
Jan 30, 2024
Insert cell
Insert cell
chart = htl.html`
${titleCard1}
${chartLegend}
${chartOnly}
`
Insert cell
titleCard1 = titleCard({
title: "Traders exposure to beef deforestation in South America",
subtitle:
"Total cattle deforestation exposure for all biomes and segmented by biome in Brazil and Paraguay, for volumes exported to the EU in 2020 (Brazil) and 2019 (Paraguay) (source: Trase Supply Chains).",
extra: html`
<label style="font-size: 14px; font-weight: bold;">Select a value:</label>
${viewof selected_value}
<label style="font-size: 14px; font-weight: bold;">Select a biome:</label>
${viewof SelectBiome}
`,
footnote:
"Total values may differ from the observed in the trade flows due to the existence of unknown municipalities of production and the harmonization between the cattle datasets. The values do not include the amount of exports for 'unknown' flows, which are the flows that couldn't be associated to a specific company due to database limitation.",
width: 1
})
Insert cell
chartLegend = legend({
colour: d3.scaleThreshold([...thresholds], colourSchemeRev),
title: selected_value,
tickFormat: ".2~s",
width: 400
})
Insert cell
Insert cell
extentRadius = d3.extent(data, (d) => d[selected_value])
Insert cell
r = d3
.scaleSqrt()
.domain(extentRadius)
.range([width * 3e-3, width * 4e-2])
Insert cell
function getByValue(map, searchValue) {
for (let [key, value] of map.entries()) {
if (value === searchValue) return key;
}
}
Insert cell
chartBubbleLegend = circleLegend({
scale: r,
ticks: 3,
tickFormat: (d, i, g) =>
i === g.length - 1
? `${formatTooltipValue(d)} ${selected_value}`
: formatTooltipValue(d),
tickWrap: false,
marginRight: 80,
marginBottom: 20
})
Insert cell
Insert cell
dataRaw = Object.assign(
await FileAttachment(
"commodity_deforestation_companies_2020.csv"
).csv({ typed: false }),
{ d: " Commodity Deforestation Total Exposure (ha)" }
)
Insert cell
data = dataRaw.filter((d) => d.biome === SelectBiome);
Insert cell
viewof SelectBiome = Inputs.select(
["ALL", "MATA ATLANTICA", "AMAZONIA", "CERRADO", "PANTANAL", "GRAN CHACO"],
{
value: "ALL",
label: "",
format: (d) => d
}
)
Insert cell
viewof selected_value = Inputs.radio(metrics_values, {
value: "Commodity Deforestation Total Exposure (ha)"
})
Insert cell
metrics_values = new Map([
[
"Commodity Deforestation Total Exposure (ha)",
"Commodity Deforestation Total Exposure (ha)"
],
["Volume (Tonnes)", "Volume (Tonnes)"]
])
Insert cell
legendItems = [
{
type: "dot",
stroke: "#bdbdbd",
fill: "#bdbdbd",
text: "No data"
}
]
Insert cell
height = width * 0.65
Insert cell
width
Insert cell
margin = ({ top: 5, bottom: 5, right: 5, left: 5 })
Insert cell
colourKey = selected_value
Insert cell
// colourScheme = traseOranges[6]
colourScheme = traseOranges[6]
Insert cell
colourSchemeRev = colourScheme.reverse()
Insert cell
thresholds = [0.05, 0.1, 0.25, 0.5, 0.75, 0.9].map((d) =>
Math.floor(
d *
d3.quantile(
data.map((d) => d[selected_value]),
0.99
)
)
)
Insert cell
colourRaw = (d) => {
if (d.data.exporter === "") return "#bdbdbd";
return d3.scaleThreshold().domain(thresholds).range(colourSchemeRev)(
d.data[colourKey]
);
}
Insert cell
keys = Object.keys(data[0]).filter((d) => d === "Volume (Tonnes)" | d === "Commodity Deforestation Total Exposure (ha)")
Insert cell
d3
.hierarchy(
d3.rollup(
data,
(v) => ({ value: d3.sum(v, (d) => d.value), data: v }),
...keys.map((k) => (d) => d[k])
)
)
Insert cell
root = d3
.hierarchy(
d3.rollup(
data,
(v) => ({ value: d3.sum(v, (d) => d.value), data: v }),
...keys.map((k) => (d) => d[k])
)
)
.sum(([, d]) => d.value)
.sort((a, b) => b.value - a.value)
Insert cell
pack = d3
.pack()
.size([
width - (margin.left + margin.right),
height - (margin.top + margin.bottom)
])
.padding(3)
Insert cell
format = d3.format(".03s")
Insert cell
formatBubbleText = (d) => {
let key = d.data.exporter;
const length = getLabelLength(key, "font: 10px var(--trase-sans-serif)");
const perimeter = d.r * 2 - 20;
const prop = (length - perimeter) / length;
if (perimeter < 50) return "";
if (length > perimeter)
key =
key.substring(0, Math.floor(key.length * (1 - prop)) - 3).trim() + "...";
return [...key.split(" "), format(d.value)];
}
Insert cell
annotate = g => {}
Insert cell
function hover(bubbles, svg, selected_value) {
const tooltip = new Tooltip();
const tooltipKey = selected_value.replace(/_/g, " ");
bubbles
.style("cursor", "pointer")
.on("touchstart", (event) => event.preventDefault())
.on("pointerenter", (event, d) => {
tooltip.position(
...tooltipOffset(tooltip, d3.pointer(event, svg.node()), width, height)
);
tooltip.show(d.data["exporter"], tooltipKeyValueMultiple(d));
})
.on("pointermove", function (event) {
let [x, y] = tooltipOffset(
tooltip,
d3.pointer(event, svg.node()),
width,
height
);
tooltip.position(x, y);
this.releasePointerCapture(event.pointerId);
})
.on("pointerout", () => tooltip.hide());
svg.append(() => tooltip.node);
}
Insert cell
tooltipKeyValueMultiple = (d) => svg`<text>
<tspan font-size="10px" fill="#839095" x="0" dy="0em">VOLUME EXPORTED TO THE EU (TONNES):</tspan>
<tspan font-family="var(--trase-sans-serif)" font-size="14px" font-weight="700" fill="#31464e" x="0" dy="1.4em">${format(
d.data["Volume (Tonnes)"]
)} </tspan>
<tspan font-size="10px" fill="#839095" x="0" dy="2.2em">COMMODITY DEFORESTATION TOTAL EXPOSURE (HA):</tspan>
<tspan font-family="var(--trase-sans-serif)" font-size="14px" font-weight="700" fill="#31464e" x="0" dy="1.4em">${d3.format(
".03s"
)(d.data["Commodity Deforestation Total Exposure (ha)"])}</tspan>
<tspan font-size="10px" fill="#839095" x="0" dy="2.2em">PROPORTIONAL CONTRIBUTION ON OVERALL DEFORESTATION:</tspan>
<tspan font-family="var(--trase-sans-serif)" font-size="14px" font-weight="700" fill="#31464e" x="0" dy="1.4em">${d3.format(
".0%"
)(d.data["Proportional contribution on overall deforestation (%)"])}</tspan>
</text>`
Insert cell
formatTooltipValue = d3.format(".03s")
Insert cell
import {
traseColours,
traseCategory1,
fonts,
traseOranges,
trasePurples,
traseGreens,
traseOrPu
} from "@trase/visual-id"
Insert cell
import { getLabelLength, legend, swatches } from "@trase/legends@376"
Insert cell
import { Tooltip, tooltipKeyValue, tooltipOffset } from "@trase/tooltip@440";
Insert cell
import { pickTextColorBasedOnBackground } from "@trase/pick-text-color-based-on-bg"
Insert cell
import { slider, select, checkbox, radio } from "@jashkenas/inputs"
Insert cell
import { titleCard } from "@trase/title-card"
Insert cell
import { circleLegend } from "@trase/legends"
Insert cell
d3 = require("d3@6")
Insert cell
htl = require("htl@0.2")
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