Public
Edited
Oct 25, 2023
1 fork
Insert cell
Insert cell
chart = {

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height * 3 + 20 ]);

for(let i = 1; i < 4; i++ ) {
const m = svg.append("g")
.attr("transform",`translate(0,${height * (i-1)})`)
.append(() => parChart(
data.filter( d => d["pov.om.pam.factor"]== i ), {opacity: 0.17} ))
m.append("g")
.call(yAxis)
if (i == 3)
m.append("g")
.call(xAxis)
}
return svg.node();
}

Insert cell
function parChart (value = [], config = {}) {
const cp = cutpoints
const line = d3.line()
.defined( ([ ,x]) => x != "*")
.x( d => xScale(d[0]))
.y( (d,i) => yScale(d[1]) + updateIndex(d,i, cp))
.curve(d3.curveCardinal.tension(0.005))

config.color = config.color ? config.color : config.color = "red"
config.opacity = config.opacity ? config.opacity : 0.2

const g = d3.create("svg:g")
const lines = g.append("g")
.selectAll("g")
.data(value)
.join("g")
lines.append("path")
.attr("d", d => line(data.row.map(key => [key, d[key]])), updateIndex)
.attr("stroke", d => d["data$migback"] == 1 ? "rgb(57, 152, 143)" : "rgb(188, 132, 53)" ) // li d => d["ahc.pam.factor"]== 1 ? '#7fcdbb' : d["ahc.pam.factor"]== 2 ? '#edf8b1' : '#2c7fb8'
.attr("fill","none")
.attr("opacity", config.opacity)
.attr("shape-rendering", "geometricPrecision")
const grid = g.append('g')
.selectAll('line')
.data(data.cat)
.join("line")
.attr("x1", d => xScale(data.row[0]))
.attr("y1", d => yScale(d) + yScale.bandwidth()/2 )
.attr("x2", d => xScale(data.row[data.row.length -1 ]))
.attr("y2", d => yScale(d) /* + yScale.bandwidth()/2 */ )
.attr("stroke", "grey")

return g.node()
}
Insert cell
Insert cell
Insert cell
chart2 = {
const colorScale = d3.scaleOrdinal()
.range(yLabel.map(d => d[1]))
.domain(yLabel.map(d => d[0]))
.unknown("#d4d4d4")

const margins = {right: 10, left: 40, top: 30, bottom:10}
const width = 1800
const height = 1200
const barHeight = 0.3
const usedData = data
//.filter( d => d["pov.om.pam.factor"] == 1)

const y = d3.scalePoint(usedData.map(d => d[""]),
[0, barHeight * (usedData.length) - margins.bottom])

const x = d3.scaleLinear()
.domain([0, data.row.length -1 ])
.range([ 0, (data.row.length - 1) * 85])
//data.row, [margins.left, (data.row.length - 1) * 87.5])


const xAxis = g => g
.attr("transform", `translate(${margins.left + 33}, ${margins.top - 3})`)
.call(d3.axisTop(x)
.ticks(8)
)
.call(g => g.select(".domain").remove())

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, barHeight * usedData.length + margins.bottom + margins.top ]);

svg.append("g")
.call(xAxis)


const seq = svg.append("g")
.attr("transform", `translate(${margins.left}, ${margins.top})` )
.selectAll("g")
.data(usedData) //
.join("g")
.attr("transform", (d,i) => `translate(0, ${d.y = y(d[""])}) `)
.attr("cluster", d => d["pov.om.pam.factor"])

const paths = seq.selectAll("rect")
.data( function(d,i){ return data.row.map(x => [d[x], d["data$migback"],x, d.ch ] )} )
.join("rect")
.attr("width", 85)
.attr("height", barHeight)
.style("fill", d => /*d[1] == "1" ?*/ colorScale(d[0]) /*: 'lightgrey' */)
.attr("x", (d,i) => d.x = x(i))
.attr("y", 0)
const legend = svg.append("g")
.selectAll("rect")
.data(yLabel)
.join("rect")
.attr("x", (d,i) => i * 12)
.attr("y", 0)
.attr("width", 10)
.attr("height", 10)
.style("fill", d => colorScale(d[0]))


function update() {
y.domain(usedData.sort(viewof order.value).map(d => d[""]));
const t = svg.transition()
.duration(750);
seq.transition(t)
.delay((d,i) => i * 2)
.attrTween("transform", d => {
const i = d3.interpolateNumber(d.y, y(d[""]));
return t => `translate(${0}, ${d.y = i(t)})`;}
);
};

function updateX(){ //linear transformation only
x.domain([d3.min(usedData.map(d => d.ch)), d3.max(usedData.map(d => d.ch)) + data.row.length ])
.range([ 0, (data.row.length + 10) * 85])
const t = svg.transition()
.duration(1150);
seq.each(function(d,i){

d3.select(this)
.selectAll("rect")
.transition(t)
.delay((d,i) => i * 500)
.attrTween("x", (d,i) => {
const j = d3.interpolateNumber(d.x, x(d[3] + i) );
return t => `${d.x = j(t)}`;}
)
});

/*
paths.transition(t)
.delay((d,i) => i * 2)
.attrTween("x", (d,i) => {
const j = d3.interpolateNumber(d.x, x(d[3] + i) );
return t => `${d.x = i(t)}`;}
) */
}
viewof order.addEventListener("input", update);
invalidation.then(() => viewof order.removeEventListener("input", update));

viewof sortX.addEventListener("click",updateX);
return svg.node();
}
Insert cell
Insert cell
y = d3.scalePoint(data.map(d => d[""]), [margin.top, 20 * data.length - margin.bottom]).domain(data.sort(viewof order.value).map(d => d[""]));

Insert cell
function updateIndex(d,i, cp){
const p = cp.get(d[0]).get(d[1])
console.log(p)
const b = (1/p.count) * p.index
p.index < p.count ? p.index++ : p.index = 1
return + (yScale.bandwidth()) * b
}
Insert cell
Insert cell
Insert cell
data.row
Insert cell
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left + 30},0)`)
.call(d3.axisLeft(yScale)
.tickFormat((d,i) => yLabel[i][0])
)
.call(g => g.select(".domain").remove())
Insert cell
/*loops through rows (time=key) */
cutpoints = data.row.reduce( (map,key) => map.set(key,
/*loops through data array */
data.reduce( (acc, curr) =>
/* counts cases for time:cat */
count(curr[key], acc), new Map()))
, new Map())
Insert cell
yScale = d3.scaleBand()
.domain(data.cat)
.range([height- margin.bottom, margin.top])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Select a data source…
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
ddata = FileAttachment("cluster@1.csv").csv()

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