Published
Edited
Apr 20, 2020
Insert cell
Insert cell
Insert cell
chunkedData = {
const clonedData = [...data];
_.mixin({
binned: (dataset, bins=1) => {
const binCount = Math.floor(dataset.length/bins);
const conditionalSlice = (d) => d.length > bins ? d.slice(d.length - bins) : d;
return conditionalSlice(_.chain(dataset)
.reverse()
.chunk(binCount)
.reverse()
.value());
}
});
const n = 50;
const chunkSize = Math.floor(data.length / n);
return _.binned(clonedData, n).map(aggregateFn);
}
Insert cell
groupedData = {
// CHANGE TO TEST
const n = 50;
const clonedData = [...data];
const length = clonedData.length;
if (length <= n) {
return clonedData;
}
// Cases:
// 1. All data is repeated so end up with smaller array.
// 2. Not enough data is duplicated.
let result = [];
let index = 0;
while(index < (length - 1)) {
const current = clonedData[index];
const next = clonedData[index + 1];

if (current.y === next.y) {
result.push([current, next]);

// Check if we have desired length
const resultLength = result.length;
const afterRemaining = length - (index + 2);
if (resultLength + afterRemaining <= n) {
console.log(`Current result length: ${resultLength}`);
console.log(`Remaining after merge: ${afterRemaining}`);
result = [...result, ...clonedData.slice(index + 2)];
break;
}
index += 2;
} else {
result.push(current);
index++;
}
}
// We iterate just once, we have two options:
// 1. Repeat, this might significantly change shape of signal
// 2. Group at the end and/or start <-- FOR NOW
const extra = result.length - n;
if (extra > 0) {
const toMerge = result.splice(result.length - (extra + 1)).flat();
result.push(toMerge);
}
return result.map(aggregateFn);
}
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, (height) * 3])
.attr("font-family", "sans-serif")
.attr("font-size", 10);
const container = svg.append('g');

const originalTicks = ticks(container.append('g'), data);

const chunkedTicks = ticks(
container.append('g')
.attr('transform', `translate(0, ${height})`),
chunkedData
);

const groupedTicks = ticks(
container.append('g')
.attr('transform', `translate(0, ${height * 2})`),
groupedData
);
return svg.node();
}
Insert cell
aggregateFn = chunk => {
if (!_.isArray(chunk)) {
return chunk;
}
const values = chunk.map(item => item.y);
const max = Math.max(...values);
const maxIndex = values.indexOf(max);

return chunk[maxIndex];
}
Insert cell
options = ({
xScale: (d, index) => index * (binWidth + binSpacing),
yScale: 0,
width: binWidth,
height: binHeight,
fill: d => colorMap(d.y),
spacing: String(binSpacing),
info: {
x: d => d.x.valueOf(),
y: d => d.y,
},
})

Insert cell
ticks = (el, data) => el.selectAll('rect')
.data(data)
.join('rect')
.attr('x', options.xScale)
.attr('y', options.yScale)
.attr('width', options.width)
.attr('height', options.height)
.style('fill', options.fill)
.style('rx', 2)
.style('ry', 2)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colorMap = d3.scaleOrdinal().range(['#BED2EB', '#FFDC4F', '#EA3B60']);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
_ = require('lodash')
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