Public
Edited
Jun 26, 2023
2 forks
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { cars as newDataset } from "@observablehq/plot-test-data"
Insert cell
newDataset
Insert cell
newDatasetData = newDataset.data
Insert cell
Insert cell
newDatasetData
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
// Select a row from the table as a reference to extract attribute names.
referenceRow = tableData[0]
Insert cell
Insert cell
// Extract all attribute names from the reference row and filter by numeric attributes.
numericAttributes = Object.keys(referenceRow).filter(key => !isNaN(referenceRow[key]))
Insert cell
Insert cell
// Convert the table data into an array of rows, where each row is an array of values for all numeric attributes.
rowData = tableData.map(row => Object.keys(row).filter(key => numericAttributes.includes(key)).map(key => row[key]))
Insert cell
// Convert the table data into an array of columns, where each column is an array of values for all numeric attributes.
columnData = numericAttributes.map(key => tableData.map(row => row[key]))
Insert cell
Insert cell
// Set the width of the table visualization.
tableWidth = width
Insert cell
columnScale = d3.scaleBand() // Get a scale object for discrete bands (columns).
.domain(d3.range(columnData.length)) // Input from zero to maximum column index.
.range([0, tableWidth]) // Output from left to right edge of drawing area (image coordinates).
.padding(0.1) // Padding between columns.
Insert cell
// Set the height of the table visualization (here, at least one pixel per row).
tableHeight = Math.max(450, rowData.length);
Insert cell
rowScale = d3.scaleBand() // Get a scale object for discrete bands (rows).
.domain(d3.range(rowData.length)) // Input from zero to maximum row index.
.range([0, tableHeight]) // Output from top to bottom edge of drawing area (image coordinates).
.padding(0) // Padding between rows.
Insert cell
Insert cell
function blackAndWhiteColorScale(data, index, value) {
const scale = d3.scaleLinear() // Get a linear scale object.
.domain(d3.extent(data[index])) // Input between minimum and maximum of data values.
.range(['black','white']); // Output interpolated colors between black and white (🛠️ Try some other colors!).
return scale(value);
}
Insert cell
Insert cell
function createTable(width, height, columnScale, rowScale, colorScale, columnData, rowData) {
// Create the SVG image.
const svg = d3.select(DOM.svg(width, height));

// Select and create a SVG group for each row.
const rows = svg.selectAll('.row') // Select all groups with class name 'row'.
.data(rowData)
.join('g')
.attr('class', 'row'); // Give each row group a class name to distinguish it from other groups in the SVG image.

// Loop throught the row group and add the table cells.
rows.each(function(cellValues, rowIndex) {
// Add colored rectangles (table cells) for each row.
d3.select(this) // Select the current row group.
.selectAll('rect') // Select all rectangles.
.data(cellValues) // Attach the data for the current row the selection.
.join('rect') // Create / update / remove rectangles for the mapping.
.attr('x', (_, i) => columnScale(i)) // Set the rectangle x position.
.attr('y', rowScale(rowIndex)) // Set the rectangle y position.
.attr('width', columnScale.bandwidth()) // Set the rectangle width.
.attr('height', rowScale.bandwidth()) // Set the rectangle height.
.style('fill', (d, i) => colorScale(columnData, i, d)); // Set the rectangle fill color.
});

// Return the HTML element for the SVG image.
return svg.node();
}
Insert cell
Insert cell
createTable(tableWidth, tableHeight, columnScale, rowScale, blackAndWhiteColorScale, columnData, rowData)
Insert cell
Insert cell
Insert cell
Insert cell
tableHeaderHeight = 30 // Height of the column header in the image.
Insert cell
Insert cell
Insert cell
// An array of available color scheme names.
colorSchemeNames = ['Blues', 'Oranges', 'Greens', 'Reds', 'Purples', 'YlOrBr', 'YlGnBu', 'Greys', 'Inferno', 'Magma', 'Plasma', 'Warm', 'Cool', 'CubehelixDefault', 'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBuGn', 'PuBu', 'PuRd', 'RdPu', 'YlGn', 'YlOrRd']
Insert cell
Insert cell
colorSchemes = columnData.map((_, i) => d3[`interpolate${colorSchemeNames[i]}`])
Insert cell
Insert cell
Insert cell
Insert cell
viewof invalidColor = Inputs.color({label: "Invalid color", value: "#ff00ff"})
Insert cell
Insert cell
isValueInvalid = {
const testValue = Number.NaN; // Try a valid number, e.g., 1.
return 'The test value is ' + (isNaN(testValue) ? 'NaN' : 'not NaN');
}
Insert cell
Insert cell
Insert cell
Insert cell
unsortExampleData = [ 5, 8, 1, 4, 9, 0, 3, 6, 4, 7 ]
Insert cell
mutable sortedExampleData = [...unsortExampleData]
Insert cell
Insert cell
{
const svg = d3.select(DOM.svg(28, 28));

svg.append('rect')
.attr('x', 2)
.attr('y', 2)
.attr('ry', 5)
.attr('width', 24)
.attr('height', 24)
.style('stroke', 'black')
.style('fill', 'steelblue')
.on('click', () => {
mutable sortedExampleData = [...unsortExampleData].sort((a, b) => a - b);
});

// 🛠️ Try adding additional event listeners to highlight the rectangle depending on whether the pointer enters or leaves the rectangle area.
// See: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
return svg.node();
}
Insert cell
Insert cell
Insert cell
import { coloredTableWithSorting } from "@mroehlig/visualization-of-multivariate-data-with-d3-colored-table-solution"
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