Published unlisted
Edited
Oct 19, 2021
1 fork
Insert cell
Insert cell
Problem: When data is categorical (and y definition is switched), brush doesn't work anymore...
Insert cell
selection // brush an axis below to see this update!
Insert cell
Insert cell
data = FileAttachment("cars.csv").csv({typed: true}) // only numeric, original data
//data = d3.csvParse(await FileAttachment("Auswertung_Büro_Parallel_1.CSV").text(), d3.autoType) // cateorical and numeric, real data
Insert cell
Insert cell
Removed in parent
viewof keyz = Inputs.select(keys, {label: "color encoding"})
Insert cell
Removed in fork
viewof keyz = {
  const form = html`<form>${Object.assign(html`<select name=select>${keys.map(key => Object.assign(html`<option>`, {value: key, textContent: key}))}</select>`, {value:"Ükh"})} <i style="font-size:smaller;">color encoding</i>`;
  form.select.onchange = () => (form.value = form.select.value, form.dispatchEvent(new CustomEvent("input")));
  form.select.onchange();
  return form;
}
Insert cell
Insert cell
Changed in fork
viewof selection = { const svg = d3.create("svg") .attr("viewBox", [0, 0, width, height]); const brush = d3.brushY() .extent([[-20, margin.top], [20, height - margin.bottom]]) .on("start brush end", brushed); // Definiere Datenlinien const path = svg.append("g") .attr("fill", "none") .attr("stroke-width", 1.5) .attr("stroke-opacity", 0.4) .selectAll("path") .data(data.slice().sort((a, b) => d3.ascending(a[keyz], b[keyz]))) .join("path") .attr("stroke", d => z(d[keyz])) .attr("d", d => line(d3.cross(keys, [d], (key, d) => [key, d[key]]))); path.append("title") .text(label); // Zeichne Achsen svg.append("g") .selectAll("g") .data(keys) .join("g") .attr("transform", d => `translate(${x(d)},0)`) .each(function(d) { d3.select(this).call(d3.axisRight(y.get(d))); }) .call(g => g.append("text") .attr("y", 10) .attr("x", -10) .attr("text-anchor", "start") .attr("fill", "currentColor") .text(d => d)) .call(g => g.selectAll("text") .clone(true).lower() .attr("fill", "none") .attr("stroke-width", 5) .attr("stroke-linejoin", "round") .attr("stroke", "white")) .call(brush); const selections = new Map(); // Funktion zum Auswählen/Abwählen function brushed({selection}, key) { if (selection === null) selections.delete(key); else selections.set(key, selection.map(y.get(key).invert)); const selected = []; path.each(function(d) {
-
const active = Array.from(selections).every(([key, [min, max]]) => d[key] >= min && d[key] <= max);
+
const active = Array.from(selections).every(([key, [max, min]]) => d[key] >= min && d[key] <= max);
//console.log(active); d3.select(this).style("stroke", active ? z(d[keyz]) : deselectedColor); if (active) { d3.select(this).raise(); selected.push(d); } }); svg.property("value", selected).dispatch("input"); } return svg.property("value", data).node(); }
Insert cell
keys = data.columns.slice(1)
Insert cell
Insert cell
//original from https://observablehq.com/@d3/brushable-parallel-coordinates
y2 = new Map(Array.from(keys, key => [key, d3.scaleLinear(d3.extent(data, d => d[key]), [margin.top, height - margin.bottom])]))

Insert cell
//imported code from https://observablehq.com/@batshaw/exercise-3-parallel-coordinates
y= {
let scales = new Map();

keys.forEach(function(attribute) {
//Some attributes are categorical type
const NumKeys=["Ükh","economy (mpg)","cylinders","displacement (cc)","power (hp)","0-60 mph (s)","weight (lb)","year"]; // too stupid to check if array is numeric, so ding it by hand...
if(!NumKeys.includes(attribute)){
scales.set(
attribute, d3.scalePoint()
.domain(data.map(d => d[attribute]))
.range([margin.top, height - margin.bottom]));
console.log(attribute + "= Text Skala : "+data.map(d => d[attribute]));
} else {
scales.set(
attribute, d3.scaleLinear()
.domain(d3.extent(data, d => d[attribute])).nice() //[0, 200000])//
.range([height - margin.top, margin.bottom]));
console.log(attribute + "= Numerische Skala :"+d3.extent(data, d => d[attribute]));
//debugger;
}

});

return scales;
}
Insert cell
x = d3.scalePoint(keys, [margin.left, width - margin.right])
Insert cell
z = d3.scaleSequential(y.get(keyz).domain().reverse(), colors)
Insert cell
line = d3.line()
.defined(([, value]) => value != null)
.y(([key, value]) => y.get(key)(value))
.x(([key]) => x(key))
Insert cell
label = d => d.name
Insert cell
colors = d3.interpolateBrBG
Insert cell
deselectedColor = "#ddd"
Insert cell
brushHeight = 50
Insert cell
margin = ({top: 30, bottom: 30, left: 10,right: 50})
Insert cell
height = 600 //keys.length * 120
Insert cell
d3 = require("d3@6")
Insert cell
import {legend as Legend} from "@d3/color-legend"
Insert cell