{"id":20133,"date":"2020-07-30T14:31:24","date_gmt":"2020-07-30T13:31:24","guid":{"rendered":"http:\/\/www.highcharts.com\/blog\/?p=20133"},"modified":"2026-01-13T09:58:35","modified_gmt":"2026-01-13T09:58:35","slug":"violin-plot","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/tutorials\/violin-plot\/","title":{"rendered":"Violin Plot"},"content":{"rendered":"<p>In this article, we will show you how to create an interactive violin plot with Highcharts.<br \/>\n&nbsp;<br \/>\nWe will start by describing the violin plot first; then, we will walk you through the code.<br \/>\nThe demos below display the 2012 Olympic <a href=\"https:\/\/raw.githubusercontent.com\/mekhatria\/demo_highcharts\/master\/viloinData.json\" target=\"_blank\" rel=\"noopener noreferrer\">male<\/a> and <a href=\"https:\/\/raw.githubusercontent.com\/mekhatria\/demo_highcharts\/master\/viloinDataFemale.json\" target=\"_blank\" rel=\"noopener noreferrer\">female<\/a> athletes&#8217; weight of the following disciplines: taekwondo, rowing, triathlon, and fencing. The violin plot visualizes the distribution shape and the probability density (athletes&#8217; weight) across each discipline compellingly and intuitively:<\/p>\n<p class=\"demo-comtainer\"><iframe style=\"width: 100%;\" title=\"Violin: The 2012 Olympic male athletes weight\" src=\"https:\/\/codepen.io\/mushigh\/embed\/zYrbpJg?height=265&amp;theme-id=light&amp;default-tab=result\" height=\"500\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\" title=\"A violin plot visualizes men distribution shape and the probability density (athletes\u2019 weight) across four disciplines\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/mushigh\/pen\/zYrbpJg\">Violin: 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 class=\"demo-container\"><iframe style=\"width: 100%;\" title=\"Violin: The 2012 Olympic female athletes weight\" src=\"https:\/\/codepen.io\/mushigh\/embed\/eYJXjVe?height=265&amp;theme-id=light&amp;default-tab=result\" height=\"500\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\" title=\"A violin plot visualizes women distribution shape and the probability density (athletes\u2019 weight) across four disciplines\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/mushigh\/pen\/eYJXjVe\">Violin: The 2012 Olympic female 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>From the charts above and thanks to the violin type plot, we can easily find a similar pattern among males and females within the same discipline. Both male and female triathlon athletes&#8217; density weight shapes show less variability compared to the other disciplines. The taekwondo athletes in both genders are widespread and have multiple clusters.<\/p>\n<p>Well, you have got the picture, the violin plot is the best chart to display and compare the density distribution of a data set.<\/p>\n<p>Now, it is time to explore the code part.<br \/>\nThe code is divided into two main sections:<\/p>\n<ol>\n<li>Process violin data.<\/li>\n<li>Create the chart.<\/li>\n<\/ol>\n<h2>Process violin data<\/h2>\n<p>The function <code>processViolin()<\/code> (check the <a href=\"https:\/\/github.com\/mekhatria\/violin-plot\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub link<\/a>) is at the heart of the violin plot. The function is built around the <a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/data-science-and-highcharts-kernel-density-estimation\/\" target=\"_blank\" rel=\"noopener noreferrer\">kernel density estimation (KDE)<\/a>. Basically, a violin plot is a KDE and its negative displayed in opposition to each other. The function <code>processViolin()<\/code> gets the data set, in our case athletes&#8217; weight, with a few extra parameters, then generate the density shape and measures of descriptive statistics:<\/p>\n<pre>function processViolin(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&#8217;s parameters:<\/p>\n<ul>\n<li><b>step<\/b> is the minimum data set unit. The step is used to sample the data set and create the KDE.<\/li>\n<li><b>precision<\/b> is used to refine the violin 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><b>densityWidth<\/b> is used to widen the violin. 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><b>args<\/b> 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>So you might wonder, how does it work in practice? Well, this is how it looks:<\/p>\n<pre>let step = 1,\r\n   precision = 0.00000000001,\r\n   width = 3;\r\n let data = processViolin(step, precision, width, rowing, taekwondo, triathlon, fencing);<\/pre>\n<p>Notice the data returned by the <code>processViolin()<\/code>. <code>data<\/code> is a set of three arrays:<\/p>\n<ul>\n<li><b>xiData<\/b> is the xAxis data generated using the step and the range of the athletes&#8217; weights data.<\/li>\n<li><b>results<\/b> include all the violin charts data.<\/li>\n<li><b>stat<\/b> is the array with all the descriptive statistical coefficients.<\/li>\n<\/ul>\n<p>Once the violin data, for each series, is generated thanks to the <code>processViolin()<\/code> function, the next step is to render the data.<\/p>\n<h2>Create a chart<\/h2>\n<p>The chart creation is pretty simple to set up. The type of the series is <code>areasplinerange<\/code>; this chart type allows us to get the violin shape using a range. The range is the result of the calculation of both the positive and negative KDE values. The option <code>inverted: true<\/code> helps to get the violin chart vertical instead of horizontal:<\/p>\n<pre>chart: {\r\n   type: \"areasplinerange\",\r\n   inverted: true,\r\n   animation: true\r\n }<\/pre>\n<p>To be sure that only the required number of the categories are displayed, be sure to restrict that number using the code below, where the min and max options have the range of the exact number of categories, in our case four: &#8220;Rowing&#8221;, &#8220;Taekwondo&#8221;, &#8220;Triathlon&#8221;, and &#8220;Fencing&#8221;.<\/p>\n<pre> yAxis: {\r\n   ..\r\n   min: 0,\r\n   max: data.results.length - 1,\r\n   ...\r\n },<\/pre>\n<p>One last trick to get the right violin shape is to get rid of the marker. Otherwise, you will end up with symbols all around the external lines of each series:<\/p>\n<pre>plotOptions: {\r\n     series: {\r\n       marker: {\r\n         enabled: false\r\n       },\r\n       ...\r\n     },<\/pre>\n<p>Up to this point, the violin charts look great. Nevertheless, for more clarity, we can add some descriptive statistical coefficients such as the median (red dot), max (blue dot), min (blue dot), first quartile (black dot), and the third quartile (black dot):<\/p>\n<p class=\"demo-container\"><iframe style=\"width: 100%;\" title=\"Violin: The 2012 Olympic male athletes weight (with statistical data)\" src=\"https:\/\/codepen.io\/mushigh\/embed\/dyGLazN?height=265&amp;theme-id=light&amp;default-tab=result\" height=\"700\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\" title=\"A violin plot visualizes men distribution shape and the probability density (athletes\u2019 weight) across each discipline with coefficients such as the median (red dot), max (blue dot), min (blue dot), first quartile (black dot), and the third quartile (black dot) \"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/mushigh\/pen\/dyGLazN\">Violin: The 2012 Olympic male athletes weight (with statistical data)<\/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 good news is all the data we need to achieve the chart above are already available in the stat array. All we have to do is to structure the information then render it using a line chart:<\/p>\n<pre>stat.forEach((e, i) =&gt; {\r\n      statData.push([]);\r\n      statData[i].push(\r\n        { x: stat[i][0], y: i, name: \"Min\", marker: { fillColor: mColor } },\r\n        {\r\n          y: i,\r\n          x: stat[i][1],\r\n          name: \"Q1\",\r\n          marker: { fillColor: qColor, radius: 4 }\r\n        },\r\n        {\r\n          y: i,\r\n          x: stat[i][2],\r\n          name: \"Median\",\r\n          marker: { fillColor: medianColor, radius: 5 }\r\n        },\r\n        {\r\n          y: i,\r\n          x: stat[i][3],\r\n          name: \"Q3\",\r\n          marker: { fillColor: qColor, radius: 4 }\r\n        },\r\n        { y: i, x: stat[i][4], name: \"Max\", marker: { fillColor: mColor } }\r\n      );\r\n    });\r\nlet statCoef = [];\r\n    for (col = 0; col &lt; 5; col++) {\r\n      statCoef.push([]);\r\n      for (line = 0; line &lt; chartsNbr; line++) {\r\n        statCoef[col].push([(x = stat[line][col]), (y = line)]);\r\n      }\r\n    }<\/pre>\n<p>The violin chart is a handy tool to visualize the data distribution and the probability density. We encourage you to use the violin chart type in your projects besides the histogram and the box plot charts, as each one of those chart types reveals a piece of your data secrets.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Step by step tutorial to create interactive violin plot using Highcharts and kernel density estimation.<\/p>\n","protected":false},"author":32,"featured_media":20136,"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-20133","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\/20133","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=20133"}],"version-history":[{"count":1,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/20133\/revisions"}],"predecessor-version":[{"id":29311,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/20133\/revisions\/29311"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/20136"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=20133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=20133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=20133"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=20133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}