Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
createGroupedBarChart = (data) => {
const dimensions = chartDimensions;

// Create the SVG container.
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, chartWidth, dimensions.height])
.attr("aria-hidden", "true")
.style("display", "block");

svg.call(xAxis);

// Append a group for each seriesHG, and a rect for each element in the seriesHG.
// Append a group for each state, and a rect for each age.
svg
.append("g")
.selectAll()
.data(data)
.join("g")
.attr("transform", ([Altersklasse]) => `translate(0, ${fy(Altersklasse)})`)
.selectAll()
.data(([, d]) => d)
.join("rect")
.attr("x", (d) => x(0))
.attr("y", (d) => y(d.Geschlecht))
.attr("width", (d) => x(d.value) - x(0))
.attr("height", y.bandwidth())
.attr("fill", (d) => colors(d.Geschlecht))
.on("pointerenter", pointerenter)
.on("pointermove", pointermove)
.on("pointerleave", pointerleave);

svg.call(yAxis);

svg
.selectAll("text")
.attr("font-family", ZHFonts.regular)
.attr("font-size", responsiveValue("12px", "14px"));

return Object.assign(svg.node(), { scales: { colors } });
}
Insert cell
viewof chartHG = createGroupedBarChart(
d3.group(
groupedData.filter((d) => d.Gewaltkategorie === "HG"),
(d) => d.Altersklasse
)
)
Insert cell
viewof chartGewalt = createGroupedBarChart(
d3.group(
groupedData.filter((d) => d.Gewaltkategorie === "AUSG"),
(d) => d.Altersklasse
)
)
Insert cell
Insert cell
chartsBreakpoint = breakpoints[2]
Insert cell
Insert cell
Insert cell
chartWidth = width >= chartsBreakpoint
? chartDimensions.width / 2
: chartDimensions.width
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// y encodes the gender categories.
y = d3
.scaleBand()
.domain(categories)
.rangeRound([0, fy.bandwidth()])
.padding(0.05)
Insert cell
xAxis = (svg) => {
function formatTick(d) {
const s = d.toLocaleString("de-CH");
return this.parentNode.nextSibling ? `\xa0${s}` : `${s}`;
}

const dimensions = chartDimensions;
const axisWidth = x.range()[1] - x.range()[0];
const pixelsPerTick = 50;
const numberOfTicksTarget = Math.max(
1,
Math.floor(axisWidth / pixelsPerTick)
);

svg
.append("g")
.attr(
"transform",
`translate(0,${dimensions.height - dimensions.margin.bottom})`
)
.call(
d3
.axisTop(x)
.ticks(3)
.tickSizeOuter(0)
.tickSize(
dimensions.height - dimensions.margin.bottom - dimensions.margin.top
)
.tickFormat(formatTick)
)
.call((g) =>
g
.selectAll(".tick text")
.attr("fill", ZHColors.black["60"])
.attr("y", 16)
.style("font-size", responsiveValue("12px", "14px"))
)
.call((g) => {
g.selectAll(".tick line").attr("stroke", ZHColors.black["60"]);
})
.call((g) =>
g
.selectAll(".tick line")
.attr("stroke-dasharray", "2,2")
.attr("stroke", ZHColors.black["60"])
)
.call((g) => {
g.selectAll(".domain").remove();
});
// .call((g) =>
// g
// .append("text")
// .attr("x", 0)
// .attr("y", 10)
// .attr("fill", ZHColors.black["60"])
// .attr("text-anchor", "start")
// .text("Median")
// );
}
Insert cell
Insert cell
Insert cell
createChartTooltip = (chartCategory, root) => {
const dimensions = chartDimensions;
const { x, y, visible, category, dataPoints } = tooltipState;

const xPosition = chartWidth / 2 > x ? `${x + 8}px` : `calc(-100% + ${x - 8}px)`;
const yPosition = `calc(-100% + ${y}px)`;

return createTooltip(
{
x: xPosition,
y: yPosition,
visible: visible && category === chartCategory,
dataPoints: dataPoints ?? []
},
root
);
}
Insert cell
viewof chartGewaltTooltip = createChartTooltip("AUSG", this)
Insert cell
viewof chartHGTooltip = createChartTooltip("HG", this)
Insert cell
pointerenter = (e, d) => {
const position = getPointerPosition(e, e.target.ownerSVGElement);

console.log(d);

setValue(
{
visible: true,
x: position[0],
y: position[1],
category: d["Gewaltkategorie"],
dataPoints: [
{
label: "Altersklasse",
value: d["Altersklasse"]
},
{
label: "Geschlecht",
value: d["Geschlecht"]
},
{
label: "Anz. Opfer",
value: d.value.toLocaleString("de-CH")
}
]
},
viewof tooltipState
);
}
Insert cell
pointermove = (e, d) => {
const position = getPointerPosition(e, e.target.ownerSVGElement);
setValue(
{
...viewof tooltipState.value,
x: position[0],
y: position[1]
},
viewof tooltipState
);
}
Insert cell
pointerleave = () => {
setValue(
{
...viewof tooltipState.value,
visible: false,
category: null
},
viewof tooltipState
);
}
Insert cell
viewof tooltipState = Inputs.input({
x: 0,
y: 0,
visible: false,
dataPoints: [],
category: null
})
Insert cell
Insert cell
// Defined sort order based on the order of the drive types
sortByGender = categories.reduce((obj, item, index) => {
return {
...obj,
[item]: index
};
}, {})
Insert cell
// Defined sort order based on the order of the drive types
sortByAge = ageClasses.reduce((obj, item, index) => {
return {
...obj,
[item]: index
};
}, {})
Insert cell
Insert cell
Insert cell
groupedData = tidy(
fetchedData,
mutate({
Geschlecht: (d) => (d.Geschlecht == "m" ? "Männlich" : "Weiblich")
}),
groupBy(
["Gewaltkategorie", "Geschlecht", "Altersklasse"],
summarize({
value: sum("Anzahl")
})
),
leftJoin(ageLength, ["Altersklasse"]),
mutate({ value: (d) => d.value / d.ak_length })
)
Insert cell
Insert cell
yearExtent = d3.extent(fetchedData, (d) => d.Ausgangsjahr)
Insert cell
categories = {
const sex = [...new Set(fetchedData.map((d) => d.Geschlecht))];

return ["Weiblich", "Männlich"];
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
ZHSex = [ZHColors.chart.lightviolet, ZHColors.chart.aquamarine] //["#7F3DA7", "#65A73D"]
Insert cell
Insert cell
css = html`<style>
.card {
background-color: ${ZHColors.black[5]};
/* color: white; */
padding: 1rem;
height: auto;
}

.cards {
max-width: 1200px;
margin: 0 auto;

display: grid;
grid-template-columns: repeat(${responsiveValue(1, 1, 2)}, 1fr);
gap: 1rem;
</style>`
Insert cell
Insert cell
formatValue = (y) => (isNaN(y) ? "N/A" : y.toLocaleString("de-CH"))
Insert cell
formatPct = (x) => (isNaN(x) ? "N/A" : (x * 100).toFixed(1))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {
colors as ZHColors,
fonts as ZHFonts
} from "@statistikzh/common-styles"
Insert cell
lit = import(`https://esm.run/lit-html@3`) // import("lit-html@3.2.1")
Insert cell
Insert cell
import { Swatches as swatches } from "d4a818dd9bd3a1cf"
Insert cell
import { createTooltip, tooltipStyle } from "67f12d77e642b388"
Insert cell
import { setValue, getPointerPosition } from "@statistikzh/utils"
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