Skip to content

Highcharts Cookbook

Some Handy JS functions

Format Large Numbers with Suffixes (K, M, B, T) in Human-readable Format

    function formatNumber(num) {
        const suffixes = ['', 'K', 'M', 'B', 'T'];
        let suffixIndex = 0;

        while (num >= 1000 && suffixIndex < suffixes.length - 1) {
            num /= 1000;
            suffixIndex++;
        }

        return num.toFixed(2) + suffixes[suffixIndex];
    }

Format Percentage in Human-readable Format

    function formatPercentage(num) {
        return (num * 100).toFixed(2) + '%';
    }

Important

all data source are in column i.e. tabular format .csv e.g.:

Country Industry Funding
Australia Image Generation 31000000
Canada Artificial Intelligence 445000000
Canada Autonomous Vehicles 84000000
France Artificial Intelligence 528000000
France Image Editing 64000000

Treemap with 2 Levels Drilldown

embed highcharts figure like below

<figure class="highcharts-figure">
  <div id="container"></div>
  <p class="highcharts-description">
      Chart showing stacked columns with grouping, allowing specific series to
      be stacked on the same column. Stacking is often used to visualize
      data that accumulates to a sum.
  </p>
</figure>
add highcharts script in extra_javascript in mkdocs.yml and add script.js in extra_javascript

Read .csv file and convert to json using d3.js v7

const response = await d3.csv('data/data.csv');

which generates the following output:

[
{ "Country": "USA", "Industry": "Tech", "Funding": 1000000 },
{ "Country": "USA", "Industry": "Healthcare", "Funding": 750000 },
{ "Country": "China", "Industry": "Manufacturing", "Funding": 2000000 },
{ "Country": "China", "Industry": "Tech", "Funding": 1500000 }
]
[
    {
        "id": "id_0_0",
        "name": "Image Generation",
        "parent": "id_0"
    },
    {
        "id": "id_0_0_0",
        "name": "Value",
        "parent": "id_0_0",
        "value": 31000000
    },
    {
        "id": "id_0",
        "name": "Australia",
        "color": "#2caffe",
        "value": 31000000
    },
]
(async () => {

    // const data = await fetch(
    //     'https://www.highcharts.com/samples/data/world-mortality.json'
    // ).then(response => response.json());

    const response = await d3.csv('data/data_treemap-2-levels-drilldown.csv');
    console.log(response);

    function convertToTreemapData(input_data, level_1_col, level_2_col, value_col, aggregation_type = 'sum') {
        const points = [];
        const data = {};
        let col1I = 0;
        let col2I = 0;

        for (const row of input_data) {
            console.log(row);
            const col1 = row[level_1_col];
            const col2 = row[level_2_col];
            const val = Number(row[value_col]);
            console.log(col1, col2, val);

            if (!data[col1]) {
                data[col1] = {};
            }
            if (!data[col1][col2]) {
                data[col1][col2] = [];
            }
            data[col1][col2].push(val);
        }

        for (const col1 in data) {
            const col1P = {
                id: 'id_' + col1I,
                name: col1,
                color: Highcharts.getOptions().colors[col1I]
            };
            let col1Val = 0;
            let col2Count = 0;

            for (const col2 in data[col1]) {
                const col2P = {
                    id: col1P.id + '_' + col2I,
                    name: col2,
                    parent: col1P.id
                };
                points.push(col2P);

                const values = data[col1][col2];
                let aggregatedValue;

                switch (aggregation_type) {
                    case 'avg':
                        aggregatedValue = values.reduce((a, b) => a + b, 0) / values.length;
                        break;
                    default: // 'sum'
                        aggregatedValue = values.reduce((a, b) => a + b, 0);
                }

                const valueP = {
                    id: col2P.id + '_0',
                    name: 'Value',
                    parent: col2P.id,
                    value: Math.round(aggregatedValue)
                };
                col1Val += valueP.value;
                points.push(valueP);
                col2I++;
                col2Count++;
            }

            if (aggregation_type === 'avg') {
                col1P.value = Math.round(col1Val / col2Count);
            } else {
                col1P.value = Math.round(col1Val);
            }
            points.push(col1P);
            col1I++;
        }
        console.log(points);
        return points;
    }

    const treemapData = convertToTreemapData(response, 'Country', 'Industry', 'Funding', 'sum');
    console.log(treemapData);

    function formatNumber(num) {
        const suffixes = ['', 'K', 'M', 'B', 'T'];
        let suffixIndex = 0;

        while (num >= 1000 && suffixIndex < suffixes.length - 1) {
            num /= 1000;
            suffixIndex++;
        }

        return num.toFixed(2) + suffixes[suffixIndex];
    }

    function formatPercentage(num) {
        return (num * 100).toFixed(2) + '%';
    }

    Highcharts.chart('container-treemap-2-levels-drilldown', {
        series: [{
            name: 'Regions',
            type: 'treemap',
            layoutAlgorithm: 'squarified',
            allowDrillToNode: true,
            animationLimit: 1000,
            dataLabels: {
                enabled: false
            },
            levels: [{
                level: 1,
                dataLabels: {
                    enabled: true
                },
                borderWidth: 3,
                levelIsConstant: false
            }, {
                level: 1,
                dataLabels: {
                    style: {
                        fontSize: '14px'
                    }
                }
            }],
            accessibility: {
                exposeAsGroupOnly: true
            },
            data: treemapData
        }],
        subtitle: {
            text: 'Click points to drill down. Source: <a href="https://www.forbes.com/lists/ai50/">Forbes 2024 AI 50 List</a>.',
            align: 'left'
        },
        title: {
            text: 'Forbes 2024 AI 50 List',
            align: 'left'
        },
        tooltip: {
            useHTML: true,
            formatter: function() {
                const point = this.point;
                console.log(point);
                // calculate percentage of total
                const totalParent = point.node.parentNode.childrenTotal;
                const percentage = point.value / totalParent;
                const formattedPercentage = formatPercentage(percentage);
                return this.point.name + ': <b>$' + formatNumber(this.point.value) + ' (' + formattedPercentage + ')</b>'
            }
        },
    });
})();

basically it set the level 1 as the parent and level 2 as the child, and the value is the funding, the field parent indicate the parent of the level 2

Chart showing stacked columns with grouping, allowing specific series to be stacked on the same column. Stacking is often used to visualize data that accumulates to a sum.