Published
Edited
Jul 18, 2022
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
nominal_columns = properties.filter(d => d.type === "string").map(d => d.key)
Insert cell
data_nominal_sets = {
var r = [];
nominal_columns.forEach(oc => {
var uv = d3.rollups(data, v => v.length, d => d[oc]);
r.push({
key: oc,
title: properties.filter(d => d.key === oc)[0].title,
unique_values_nb: uv.length,
unique_values_and_counts: uv
});
});
return r.sort((a, b) => (a.unique_values_nb > b.unique_values_nb ? -1 : 1));
}
Insert cell
viewof data_nominal_sets_selected = Table(data_nominal_sets, {
format: {
unique_values_nb: sparkbar(
d3.max(data_nominal_sets, d => d.unique_values_nb)
)
},
columns: ["title", "key", "unique_values_nb"]
})
Insert cell
function sparkbar(max) {
return x => html`<div style="
background: lightgray;
width: ${(100 * x) / max}%;
float: left;
padding-right: 3px;
box-sizing: border-box;
color: black;">${x.toLocaleString("en")}`;
}
Insert cell
viewof nominal_sets_bar_chart = vl
.markBar()
.data(data_nominal_sets_selected)
.encode(
vl
.x()
.fieldN("title")
.sort({ field: "unique_values_nb", op: "max", order: "descending" }),
vl.y().fieldQ("unique_values_nb")
)
.render()
Insert cell
Insert cell
numerical_columns = properties.filter(
(d) => d.type === "number" || d.type === "integer"
)
Insert cell
numerical_columns_table = Table(numerical_columns, {
columns: ["title", "key", "unit"],
layout: "auto"
})
Insert cell
Insert cell
Insert cell
viewof s_m_columns = Table(numerical_columns, {
value: numerical_columns.filter(e =>
[
"voe_tot",
"voe_tot_f",
"acc_neobac",
"acc_bg_mention",
"acc_aca_orig_idf",
"taux_adm_psup"
].includes(e.key)
),
columns: ["title", "key", "unit"],
layout: "auto"
})
Insert cell
scatterplot_matrix_columns = s_m_columns.slice().map(e => e.key)
Insert cell
Insert cell
viewof s_m_color_column = Select(
new Map(
data_nominal_sets.map(e => [`${e.title} - (${e.unique_values_nb})`, e.key])
),
{
value: "fili",
label: "Color encoding for the scatterplot matrix"
}
)
Insert cell
// Can prevent the scatterplot matrix to refresh
// viewof button = html`<form>${Object.assign(
// html`<button type=button>Re-draw scatterplot matrix`,
// {
// onclick: event =>
// event.currentTarget.dispatchEvent(
// new CustomEvent("input", { bubbles: true })
// )
// }
// )}`
Insert cell
Insert cell
scatterplot_matrix_label = swatches({ color: z })
Insert cell
scatterplot_matrix = {
// button;
const svg = d3
.select(DOM.svg(width, height))
.attr("viewBox", `${-padding} 0 ${width} ${height}`)
.style("max-width", "100%")
.style("height", "auto")
.style("background-color", "white");

const g = svg.append("g").call(xAxis);

svg.append("g").call(yAxis);

const cell = svg
.append("g")
.selectAll("g")
.data(
triangular(d3.range(scatterplot_matrix_columns.length)) // triangular inf. mat.
// d3.cross(
// d3.range(scatterplot_matrix_columns.length),
// d3.range(scatterplot_matrix_columns.length)
// ) //full mat.
)
.join("g")
.attr("transform", ([i, j]) => `translate(${i * size},${j * size})`);

cell
.append("rect")
.attr("fill", "none")
.attr("stroke", "#aaa")
.attr("x", padding / 2 + 0.5)
.attr("y", padding / 2 + 0.5)
.attr("width", size - padding)
.attr("height", size - padding);

cell.each(function([i, j]) {
d3.select(this)
.selectAll("circle")
.data(
data.filter(
d =>
!isNaN(d[scatterplot_matrix_columns[i]]) &&
!isNaN(d[scatterplot_matrix_columns[j]])
)
)
.join("circle")
.attr("cx", d => x[i](d[scatterplot_matrix_columns[i]]))
.attr("cy", d => y[j](d[scatterplot_matrix_columns[j]]));
});

const circle = cell
.selectAll("circle")
.attr("r", 3)
.attr("fill-opacity", 0.4)
.attr("fill", d => z(d[s_m_color_column]));

svg
.append("g")
.style("font", "bold 10px sans-serif")
.selectAll("text")
.data(
scatterplot_matrix_columns.map(
e => properties.filter(d => d.key === e)[0].title
)
)
.join("text")
.attr("transform", (d, i) => `translate(${i * size},${i * size})`)
.attr("x", padding)
.attr("y", padding)
.attr("dy", ".71em")
.text(d => d);

svg
.append("g")
.attr("transform", "translate(610,20)")
.append(() => swatches({ color: z }));

// svg.call(
// d3
// .zoom()
// .extent([[0, 0], [width, height]])
// .scaleExtent([1, 1]) // Set zoom extent
// .on("zoom", zoomed)
// );
// function zoomed({ transform }) {
// svg.attr("transform", transform);
// }

return svg.node();
}
Insert cell
function triangular(vect) {
const list = [];
vect.forEach(e => vect.slice(e).forEach(f => list.push([e, f])));
return list;
}
Insert cell
x = scatterplot_matrix_columns.map(c =>
d3
.scaleLinear()
.domain(d3.extent(data, d => d[c]))
.rangeRound([padding / 2, size - padding / 2])
)
Insert cell
y = x.map(x => x.copy().range([size - padding / 2, padding / 2]))
Insert cell
z = d3
.scaleOrdinal()
.domain(Array.from(new Set(data.map(d => d[s_m_color_column]))))
.range(d3.schemeSet1)
Insert cell
xAxis = {
const axis = d3
.axisBottom()
.ticks(6)
.tickSize(size * scatterplot_matrix_columns.length);
return g =>
g
.selectAll("g")
.data(x)
.join("g")
.attr("transform", (d, i) => `translate(${i * size},0)`)
.each(function(d) {
return d3.select(this).call(axis.scale(d));
})
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").attr("stroke", "#ddd"));
}
Insert cell
yAxis = {
const axis = d3
.axisLeft()
.ticks(6)
.tickSize(-size * scatterplot_matrix_columns.length);
return g =>
g
.selectAll("g")
.data(y)
.join("g")
.attr("transform", (d, i) => `translate(0,${i * size})`)
.each(function(d) {
return d3.select(this).call(axis.scale(d));
})
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").attr("stroke", "#ddd"));
}
Insert cell
//width = 1500 // Responsive max width (from obs std lib) : 954
Insert cell
height = width
Insert cell
size = (width - (scatterplot_matrix_columns.length + 1) * padding) /
scatterplot_matrix_columns.length +
padding
Insert cell
padding = 28
Insert cell
Insert cell
import { header } from "@aymericbr/header-for-sub-notebook-to-redirect-to-its-parent"
Insert cell
import { toc } from "@aymericbr/indented-table-of-content"
Insert cell
import { headings_numbering } from "@aymericbr/multilevel-numbering-headings"
Insert cell
headings_numbering
Insert cell
import {
properties,
data
} from "@aymericbr/in-depth-getting-data-and-its-structure"
Insert cell
d3 = require("d3")
Insert cell
import { swatches } from "@d3/color-legend"
Insert cell
import { Table, Search, Select, Range } from "@observablehq/inputs"
Insert cell
import { vl } from "@vega/vega-lite-api"
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