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.