Let's continue our tutorial with the mtcars example dataset, but adding 2 new columns to showcase funkyheatmapjs, and customizing the display.
Load scripts
First, include in your html page the 2 peer dependencies and funkyheatmapjs itself:
<script type="text/javascript" src="https://unpkg.com/d3@7"></script>
<script type="text/javascript" src="https://unpkg.com/lodash@4/lodash.min.js"></script>
<script type="module" src="https://unpkg.com/funkyheatmapjs"></script> Load and render data
Then, load the data and add custom columns:
d3.csv('mtcars.csv').then((data) => {
data = d3.sort(data, (a, b) => d3.ascending(+b.mpg, +a.mpg));
data = data.slice(0, 20);
data.forEach((d, i) => {
d.schema = i % 2 ? "electric.png" : "ice.png";
d.engine_type = i % 2 ? 'Electric' : 'Gas';
d.engine_type += ` (${d.hp}🐴)`;
d.load = [(i % 3) / 6, ((i + 1) % 3) / 6, 0];
d.load[2] = 1 - d.load[0] - d.load[1];
});
}); Here, the schema column refers to images with their absolute or relative (in this case) URIs. The load column has array as data, of equal sizes for each datapoint. And the engine_type column defines a custom text for the tooltip.
Adding configuration
Configuration of funkyheatmapjs is done via parameters to funkyheatmap call. In this example we will use all available parameters: column_info, column_groups, row_info, row_groups, palettes and legends.
const column_info = [
{id: "model", group: null, name: "Name", geom: "text", palette: null},
{id: "mpg", group: "overall_1", name: "Miles / gallon", geom: "bar", palette: "palette1", options: {width: 4}},
{id: "cyl", group: "overall_2", name: "Number of cylinders", geom: "bar", palette: "palette2", options: {width: 4}},
{id: "disp", group: "group1", name: "Displacement (cu.in.)", geom: "funkyrect", palette: "palette1"},
{id: "hp", group: "group1", name: "Gross horsepower", geom: "funkyrect", palette: "palette1"},
{id: "drat", group: "group1", name: "Rear axle ratio", geom: "funkyrect", palette: "palette1"},
{id: "wt", group: "group1", name: "Weight (1000 lbs)", geom: "funkyrect", palette: "palette1"},
{id: "qsec", group: "group2", name: "1/4 mile time", geom: "circle", palette: "palette2"},
{id: "vs", group: "group2", name: "Engine", geom: "circle", palette: "palette2"},
{id: "am", group: "group2", name: "Transmission", geom: "circle", palette: "palette2"},
{id: "gear", group: "group2", name: "# Forward gears", geom: "circle", palette: "palette2"},
{id: "carb", group: "group2", name: "# Carburetors", geom: "circle", palette: "palette2"},
{id: "schema", group: "group2", name: "Schema", geom: "image", width: 25, id_hover_text: "engine_type"},
{id: "load", group: "group2", name: "Load", geom: "pie", palette: "load"}
]; column_info tells funkyheatmapjs which columns to display (all by default) and how. id refers to the column name in the data, and name is the label for the column. geom is the type of visualization for the column. Compared to the Basic usage example, we changed some numerical columns to be displayed as bars or circles, and added columns for images and pie charts.
Image column requires a width option, in pixels. For the bar columns the width is in standard column widths, here 4 means one bar columns is as wide as 4 standard columns.
We can also specify palette to configure color scheme for the column, and group them thematically under a header with group option.
Finally, id_hover_text configures this column to display a tooltip text from another column when move hovers the display element.
const column_groups = [
{level1: "Overall", level2: "Left", group: "overall_1", palette: "none"},
{level1: "Overall", level2: "Right", group: "overall_2", palette: "none"},
{level1: "Group 1", group: "group1", palette: "palette1"},
{level1: "Group 2", group: "group2", palette: "palette2"}
]; column_groups is used to configure the display of column group headers, if they are used in column_info. Value of group should match between this parameter and column_info. The display name is specified in levelX properties, the default is the capitalized group ID. More than one level allows nesting the column groups.
const row_groups = [
{group: 'first', Group: 'First'},
{group: 'second', Group: 'Seconds'}
]; row_groups is used to configure the names of the row groups: these are displayed above each group, and split the dataframe into blocks. When sorting by column, each row group is sorted independently.
const row_info = data.map((_, i) => {
return {group: i < 10 && 'first' || 'second'}
}); row_info tells funkyheatmapjs which rows belong to which group. It is expected that rows are already sorted by groups, such that all rows from the same group are adjacent. Here we just put the first 10 rows into one group, and the last into another as an example.
const palettes = {
overall: "Greys",
palette1: "Blues",
palette2: "Reds",
load: {
colors: ["#82daf2", "#ba4e79", "#ffffff"],
names: ['A', 'B', 'C']
}
}; palettes map our arbitrary names for color schemes to predefined palettes (see defaultPalettes) or custom palettes. Custom palettes could be simple arrays, or named colors. We need named colors for pie chart geom.
const legends = [
{
title: "Type",
geom: "image",
size: 25,
labels: ['Electric', 'Gas'],
values: ['electric.png', 'ice.png']
},
{
title: "Oranges",
palette: "palette2",
geom: "circle"
}
]; legends is used to customize legend display. Legends will display once for each palette used in the columns. Here we redefine the legend for palette2 palette, but keep the default for palette1. We also add a legend for our image column.
Finally, we call the funkyheatmap function with all the parameters:
<div id="app"></div>
<script type="module">
import { default as funkyheatmap } from 'https://unpkg.com/funkyheatmapjs';
d3.csv('mtcars.csv').then((data) => {
data = d3.sort(data, (a, b) => d3.ascending(+b.mpg, +a.mpg));
data = data.slice(0, 20);
data.forEach((d, i) => {
d.schema = i % 2 ? "electric.png" : "ice.png";
d.engine_type = i % 2 ? 'Electric' : 'Gas';
d.engine_type += ` (${d.hp}🐴)`;
d.load = [(i % 3) / 6, ((i + 1) % 3) / 6, 0];
d.load[2] = 1 - d.load[0] - d.load[1];
});
const row_info = data.map((_, i) => {
return {group: i < 10 && 'first' || 'second'}
});
d3.select("#app").node().appendChild(funkyheatmap(
data,
column_info,
row_info,
column_groups,
row_groups,
palettes,
legends,
{rowHeight: 28}, // position arguments
{ // heatmap options
labelGroupsAbc: true,
colorByRank: true
}
));
});
</script> Here we also used PositionArgs options and HeatmapOptions options, which allow additional configuration of sizes and positions, and of behavior and theme options.
Result
You can see a realistic usage example in the next tutorial.