{"id":20157,"date":"2020-08-10T11:45:27","date_gmt":"2020-08-10T10:45:27","guid":{"rendered":"http:\/\/www.highcharts.com\/blog\/?p=20157"},"modified":"2026-01-13T09:58:52","modified_gmt":"2026-01-13T09:58:52","slug":"density-chart","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/tutorials\/density-chart\/","title":{"rendered":"Density chart"},"content":{"rendered":"<p>In this tutorial, we will show you how to create multiple density plots, also know as ridgeline plot, using the <a href=\"https:\/\/www.highcharts.com\/demo\/areaspline\" target=\"_blank\" rel=\"noopener noreferrer\">Area Spline<\/a> chart type. As you will see from the demo below, out result doesn\u2019t look much like our \u2018default\u2019 Area Spline chart demo, but here is where Highcharts really excels: While 99% of use cases can be satisfied with running our charts with all default settings, a lot of fun can be had by examining the API as well as considering what you want your data story to be and how to best pre-process your data to that end.<\/p>\n<p>In this tutorial, we will do just that, continuing our exploration of the super-useful <a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/data-science-and-highcharts-kernel-density-estimation\/\" target=\"_blank\" rel=\"noopener noreferrer\">Kernel Density Estimation<\/a>. We used a Gaussian kernel function in previous tutorials to create a single density chart and violin chart types. And you might ask: \u201cwait a second, isn\u2019t a violin chart and the density chart, in essence, the same chart?\u201d And you would be right. A density chart is basically a violin chart split down the middle, where only one of the halves is used. Even at half size, the density chart doesn\u2019t lose any information, as the left and right side of the violin is just a mirror image of each other.<\/p>\n<p>So, when would you use a violin or density chart? Both chart types are used to visualize a data distribution and its probability density. The shape of both charts gets tinner in lower density values and thicker in higher density values. While they can both be used to show the same data, you might consider going with a density chart for compact and straightforward data distribution visualization. Use the violin chart to display an attractive density distribution with descriptive statistical coefficients.<\/p>\n<p>Good? Let\u2019s return to our main subject and harness the density type chart&#8217;s power in comparing multiple series.<\/p>\n<p>The <a href=\"https:\/\/codepen.io\/mushigh\/pen\/wvMVMma\" target=\"_blank\" rel=\"noopener noreferrer\">demo below<\/a> displays the weight density of the 2012 Olympic male athletes for six disciplines:<\/p>\n<p class=\"demo-container\"><iframe style=\"width: 100%;\"  src=\"https:\/\/codepen.io\/mushigh\/embed\/wvMVMma?height=265&amp;theme-id=light&amp;default-tab=result\" height=\"550\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\" title=\"Multiple area chart display the weight density of the 2012 Olympic male athletes for six disciplines. By Mustapha Mekhatria\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/mushigh\/pen\/wvMVMma\">Density charts: The 2012 Olympic male athletes weight<\/a> by mustapha mekhatria<br \/>\n(<a href=\"https:\/\/codepen.io\/mushigh\">@mushigh<\/a>) on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<p>The chart is easy to read thanks to the density shape and the linear gradient. The audience can see and analyze the data spread using the chart shape, and compare the weight using the color gradient.<br \/>\nThe code behind the chart is also easy to understand. The main function that processes the density data <code>processDensity()<\/code> (check the <a href=\"https:\/\/github.com\/mekhatria\/density-plot\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub link<\/a>) is inspired by the article <a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/data-science-and-highcharts-kernel-density-estimation\/\" target=\"_blank\" rel=\"noopener noreferrer\">Kernel Density Estimation<\/a>. The function gets four main parameters and returns three arrays:<\/p>\n<pre>function processDensity(step, precision, densityWidth, ...args) {\r\n  \u2026\r\n  return {\r\n    xiData,\r\n    results,\r\n    stat\r\n  };\r\n}<\/pre>\n<p>Here is the description of the function\u2019s parameters:<\/p>\n<ul>\n<li><code>step<\/code> is the minimum data set unit. The step is used to sample the data set and create the KDE.<\/li>\n<li><code>precision<\/code> is used to refine the density plot at the extremities, and in the thin spots, the smallest this parameter is the more points you get on the extremities and the thin spots on the chart.<\/li>\n<li><code>densityWidth<\/code> is used to widen the density. This parameter should be equal to 1 to reflect the result of the KDE values. Nevertheless, for visibility purposes, you are free to change the <code>densityWidth<\/code> to get a wider and visible shape.<\/li>\n<li><code>args<\/code> is one or many arrays that represent the data set. In our case, args is four arrays of weight athletes, one array for each discipline.<\/li>\n<\/ul>\n<p>The code below is an example of how to use the function:<\/p>\n<pre>let step = 1,\r\n  precision = 0.00000000001,\r\n  width = 15;\r\nlet data = processDensity(\r\n  step,\r\n  precision,\r\n  width,\r\n  dataArray[0], \/\/triathlon,\r\n  dataArray[1], \/\/badminton,\r\n  dataArray[2], \/\/fencing,\r\n  dataArray[3], \/\/rowing,\r\n  dataArray[4], \/\/handball,\r\n  dataArray[5], \/\/cycling,\r\n  dataArray[6] \/\/gymnastics\r\n);<\/pre>\n<p>Here is the description of the returned arrays:<\/p>\n<ul>\n<li><code>xiData<\/code> is the xAxis data generated using the step and the range of the athletes\u2019 weights data.<\/li>\n<li><code>results<\/code> include all the density charts data.<\/li>\n<li><code>stat<\/code> is the array with all the descriptive statistical coefficients.<\/li>\n<\/ul>\n<p>Once the density data, for each series, is generated thanks to the <code>processDensity()<\/code> function, the next step is to render the data.<\/p>\n<p>To visualize the data an <code>areasplinerange<\/code> type chart is used, as the <code>processDensity()<\/code> returns a data array results according to the <code>areasplinerange<\/code> format.<\/p>\n<pre>  Highcharts.chart(\"container\", {\r\n        chart: {\r\n          type: \"areasplinerange\",\r\n          \u2026<\/pre>\n<p>To create the color gradient effect we use the <code>linearGradient<\/code> option:<\/p>\n<pre>events: {\r\n  render() {\r\n    if (!redrawing) {\r\n      redrawing = true;\r\n\r\n      this.series.forEach((s) =&gt; {\r\n        s.update({\r\n          fillColor: {\r\n            linearGradient: [0, 0, this.plotWidth, 0],\r\n            stops: [\r\n              [0, Highcharts.color(\"yellow\").setOpacity(0).get(\"rgba\")],\r\n              [0.25, \"orange\"],\r\n              [0.5, \"red\"],\r\n              [0.6, \"purple\"]\r\n            ]\r\n          }\r\n        });\r\n      });\r\n      redrawing = false;\r\n    }\r\n  }\r\n}<\/pre>\n<p>Be sure to use the <code>linearGradient<\/code> in an <code>event<\/code> under the <code>chart<\/code> feature; otherwise, the gradient effect will not be the same in different screen sizes.<\/p>\n<p>By now, you are well equipped to create a compelling density chart with Highcharts. Feel free to try this code to create an interactive density chart or to come up with your own algorithm then share it with the community in the comment section below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Step by step tutorial to create interactive ridgeline plot using Highcharts and kernel density estimation.<\/p>\n","protected":false},"author":32,"featured_media":21840,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"meta_title":"","meta_description":"","hc_selected_options":[],"footnotes":""},"categories":[210],"tags":[1063,1094],"coauthors":[699],"class_list":["post-20157","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-data-visualization","tag-highcharts-core"],"_links":{"self":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/20157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/comments?post=20157"}],"version-history":[{"count":1,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/20157\/revisions"}],"predecessor-version":[{"id":29313,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/20157\/revisions\/29313"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/21840"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=20157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=20157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=20157"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=20157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}