I am trying to create a boxplot in Google Charts. The official documentation (see the bottom of the page) works with loading the actual dataset and calculating the stats within javascript; however, I am planning to calculate the stats (i.e. min, max, quartiles, median) elsewhere and read them in.
I tried that by creating a DataTable and directly inputting my stats (compare the snippet below to the linked documentation above). Although I can get the table and it looks fine, nothing is rendered within the boxplot.
The only thing that I can think of is that somehow when using arrayToDataTable, ids are lost so chart cannot get the right elements.
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawBoxPlot);
google.charts.load('current', {
'packages': ['table']
});
google.charts.setOnLoadCallback(drawTable);
function drawBoxPlot() {
var data = google.visualization.arrayToDataTable(
[
[{
label: 'Var',
type: 'string'
},
{
label: 'Max',
id: 'max',
type: 'number',
role: 'interval'
},
{
label: 'Min',
id: 'min',
type: 'number',
role: 'interval'
},
{
label: '1st Q',
id: 'firstQuartile',
type: 'number',
role: 'interval'
},
{
label: 'Median',
id: 'median',
type: 'number',
role: 'interval'
},
{
label: '3rd Q',
id: 'thirdQuartile',
type: 'number',
role: 'interval'
}
],
['A', 120, 85, 93, 100, 107],
['B', 140, 90, 104, 120, 127],
['C', 140, 100, 111, 130, 136],
['D', 95, 85, 86.5, 90, 93.5],
['E', 120, 85, 93, 100, 107],
['F', 140, 90, 104, 120, 127],
['G', 140, 100, 111, 130, 136],
['H', 95, 85, 86.5, 90, 93.5],
['I', 120, 85, 93, 100, 107],
['J', 140, 90, 104, 120, 127],
['K', 140, 100, 111, 130, 136],
['L', 95, 85, 86.5, 90, 93.5]
]);
var options = {
title: 'Box Plot',
height: 500,
legend: {
position: 'none'
},
hAxis: {
gridlines: {
color: '#fff'
}
},
lineWidth: 0,
series: [{
'color': '#D3362D'
}],
intervals: {
barWidth: 1,
boxWidth: 1,
lineWidth: 2,
style: 'boxes'
},
interval: {
max: {
style: 'bars',
fillOpacity: 1,
color: '#777'
},
min: {
style: 'bars',
fillOpacity: 1,
color: '#777'
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('box_plot'));
chart.draw(data, options);
}
function drawTable() {
var data = google.visualization.arrayToDataTable(
[
[{
label: 'Var',
type: 'string'
},
{
label: 'Max',
id: 'max',
type: 'number',
role: 'interval'
},
{
label: 'Min',
id: 'min',
type: 'number',
role: 'interval'
},
{
label: '1st Q',
id: 'firstQuartile',
type: 'number',
role: 'interval'
},
{
label: 'Median',
id: 'median',
type: 'number',
role: 'interval'
},
{
label: '3rd Q',
id: 'thirdQuartile',
type: 'number',
role: 'interval'
}
],
['A', 120, 85, 93, 100, 107],
['B', 140, 90, 104, 120, 127],
['C', 140, 100, 111, 130, 136],
['D', 95, 85, 86.5, 90, 93.5],
['E', 120, 85, 93, 100, 107],
['F', 140, 90, 104, 120, 127],
['G', 140, 100, 111, 130, 136],
['H', 95, 85, 86.5, 90, 93.5],
['I', 120, 85, 93, 100, 107],
['J', 140, 90, 104, 120, 127],
['K', 140, 100, 111, 130, 136],
['L', 95, 85, 86.5, 90, 93.5]
]);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(data, {
showRowNumber: true,
width: '100%',
height: '100%'
});
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="box_plot"></div>
<div id="table_div"></div>
first, you can load multiple packages at the same time,
only need to load google once...
google.charts.load('current', {
packages: ['corechart', 'table']
}).then(function () {
drawBoxPlot();
drawTable();
});
next, your data table is missing all of the series columns required by the box plot,
you're only providing the data roles / intervals.
notice in their example, there are 7 series columns, then the intervals...
var data = new google.visualization.DataTable();
data.addColumn('string', 'x');
data.addColumn('number', 'series0');
data.addColumn('number', 'series1');
data.addColumn('number', 'series2');
data.addColumn('number', 'series3');
data.addColumn('number', 'series4');
data.addColumn('number', 'series5');
data.addColumn('number', 'series6');
data.addColumn({id:'max', type:'number', role:'interval'});
data.addColumn({id:'min', type:'number', role:'interval'});
data.addColumn({id:'firstQuartile', type:'number', role:'interval'});
data.addColumn({id:'median', type:'number', role:'interval'});
data.addColumn({id:'thirdQuartile', type:'number', role:'interval'});
and if we look closer, they are using function getBoxPlotValues to format their array, before drawing the chart.
data.addRows(getBoxPlotValues(array));
so they start with their values for the vertical lines within each box plot...
these are the values for the series columns.
var array = [
['a', 100, 90, 110, 85, 96, 104, 120],
['b', 120, 95, 130, 90, 113, 124, 140],
['c', 130, 105, 140, 100, 117, 133, 139],
['d', 90, 85, 95, 85, 88, 92, 95],
['e', 70, 74, 63, 67, 69, 70, 72],
['f', 30, 39, 22, 21, 28, 34, 40],
['g', 80, 77, 83, 70, 77, 85, 90],
['h', 100, 90, 110, 85, 95, 102, 110]
];
then they use getBoxPlotValues to add the values for the data roles / intervals.
following is the array of values returned by getBoxPlotValues
[
["a",100,90,110,85,96,104,120,120,85,93,100,107],
["b",120,95,130,90,113,124,140,140,90,104,120,127],
["c",130,105,140,100,117,133,139,140,100,111,130,136],
["d",90,85,95,85,88,92,95,95,85,86.5,90,93.5],
["e",70,74,63,67,69,70,72,74,63,68,70,71],
["f",30,39,22,21,28,34,40,40,21,25,30,36.5],
["g",80,77,83,70,77,85,90,90,70,77,80,84],
["h",100,90,110,85,95,102,110,110,85,92.5,100,106]
]
it's the same series values, with the intervals added to the end of each row.
if you want to feed your values directly, your array needs to look similar to the above.
see following working snippet...
google.charts.load('current', {
packages: ['corechart', 'table']
}).then(function() {
drawBoxPlot();
drawTable();
});
function drawBoxPlot() {
var data = google.visualization.arrayToDataTable(
[
[{
label: 'Var',
type: 'string'
},
{
label: 'series0',
type: 'number'
},
{
label: 'series1',
type: 'number'
},
{
label: 'series2',
type: 'number'
},
{
label: 'series3',
type: 'number'
},
{
label: 'series4',
type: 'number'
},
{
label: 'series5',
type: 'number'
},
{
label: 'series6',
type: 'number'
},
{
label: 'Max',
id: 'max',
type: 'number',
role: 'interval'
},
{
label: 'Min',
id: 'min',
type: 'number',
role: 'interval'
},
{
label: '1st Q',
id: 'firstQuartile',
type: 'number',
role: 'interval'
},
{
label: 'Median',
id: 'median',
type: 'number',
role: 'interval'
},
{
label: '3rd Q',
id: 'thirdQuartile',
type: 'number',
role: 'interval'
}
],
["a", 100, 90, 110, 85, 96, 104, 120, 120, 85, 93, 100, 107],
["b", 120, 95, 130, 90, 113, 124, 140, 140, 90, 104, 120, 127],
["c", 130, 105, 140, 100, 117, 133, 139, 140, 100, 111, 130, 136],
["d", 90, 85, 95, 85, 88, 92, 95, 95, 85, 86.5, 90, 93.5],
["e", 70, 74, 63, 67, 69, 70, 72, 74, 63, 68, 70, 71],
["f", 30, 39, 22, 21, 28, 34, 40, 40, 21, 25, 30, 36.5],
["g", 80, 77, 83, 70, 77, 85, 90, 90, 70, 77, 80, 84],
["h", 100, 90, 110, 85, 95, 102, 110, 110, 85, 92.5, 100, 106]
]);
var options = {
title: 'Box Plot',
height: 500,
legend: {
position: 'none'
},
hAxis: {
gridlines: {
color: '#fff'
}
},
lineWidth: 0,
series: [{
color: '#D3362D'
}],
intervals: {
barWidth: 1,
boxWidth: 1,
lineWidth: 2,
style: 'boxes'
},
interval: {
max: {
style: 'bars',
fillOpacity: 1,
color: '#777'
},
min: {
style: 'bars',
fillOpacity: 1,
color: '#777'
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('box_plot'));
chart.draw(data, options);
}
function drawTable() {
var data = google.visualization.arrayToDataTable(
[
[{
label: 'Var',
type: 'string'
},
{
label: 'Max',
id: 'max',
type: 'number',
},
{
label: 'Min',
id: 'min',
type: 'number',
},
{
label: '1st Q',
id: 'firstQuartile',
type: 'number',
},
{
label: 'Median',
id: 'median',
type: 'number',
},
{
label: '3rd Q',
id: 'thirdQuartile',
type: 'number',
}
],
['A', 120, 85, 93, 100, 107],
['B', 140, 90, 104, 120, 127],
['C', 140, 100, 111, 130, 136],
['D', 95, 85, 86.5, 90, 93.5],
['E', 120, 85, 93, 100, 107],
['F', 140, 90, 104, 120, 127],
['G', 140, 100, 111, 130, 136],
['H', 95, 85, 86.5, 90, 93.5],
['I', 120, 85, 93, 100, 107],
['J', 140, 90, 104, 120, 127],
['K', 140, 100, 111, 130, 136],
['L', 95, 85, 86.5, 90, 93.5]
]);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(data, {
showRowNumber: true,
width: '100%',
height: '100%'
});
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="box_plot"></div>
<div id="table_div"></div>
note: the table chart does not use any data roles,
I would remove role: 'interval' from the columns used there...
I want to draw a chart with 4 lines, with filling between 2 specific lines named Max and Min. The library I'm using is Javascript Chartjs.
I have read the chart area doc (https://www.chartjs.org/docs/latest/charts/area.html) and this answer https://stackoverflow.com/a/45398867/10250051
However, the graph still fills the whole area under the Max line instead of stopping at the min line.
$(document).ready(function(){
var ctx = document.getElementById('mixed-api').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1,2,3,4,5,6,7],
datasets: [
{
label: 'Median',
data: [20, 20, 20, 20, 20, 20, 20],
fill: false,
borderColor: 'rgb(0, 0, 0)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Min',
data: [10, 10, 10, 10, 10, 10, 10],
fill: false,
borderColor: 'red',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Max',
data: [30, 30, 30, 30, 30, 30, 30],
fill: '-1',
borderColor: 'red',
tension: 0.1,
backgroundColor: 'rgba(255,193,8,0.5)'
},
{
label: 'Random',
data: [5, 10, 15, 20, 25, 30, 35],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'Energy (kW)'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Time'
}
}],
pointLabels: {
fontStyle: 'bold',
},
plugins: {
filler: {
propagate: false
}
},
}
}
});
});
Wrong graph
Your code is working fine, only thing I can think of is that you are using an outdated version of the lib, with the latest V2 (2.9.4) release and V3 release its working as intended, see examples:
V2.9.4
var ctx = document.getElementById('chartJSContainer').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [
{
label: 'Median',
data: [20, 20, 20, 20, 20, 20, 20],
fill: false,
borderColor: 'rgb(0, 0, 0)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Min',
data: [10, 10, 10, 10, 10, 10, 10],
fill: false,
borderColor: 'red',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Max',
data: [30, 30, 30, 30, 30, 30, 30],
fill: '-1',
borderColor: 'red',
tension: 0.1,
backgroundColor: 'rgba(255,193,8,0.5)'
},
{
label: 'Random',
data: [5, 10, 15, 20, 25, 30, 35],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'Energy (kW)'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Time'
}
}],
pointLabels: {
fontStyle: 'bold',
},
plugins: {
filler: {
propagate: false
}
},
}
}
});
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" integrity="sha512-hZf9Qhp3rlDJBvAKvmiG+goaaKRZA6LKUO35oK6EsM0/kjPK32Yw7URqrq3Q+Nvbbt8Usss+IekL7CRn83dYmw==" crossorigin="anonymous"></script>
</body>
V3:
var ctx = document.getElementById('chartJSContainer').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [
{
label: 'Median',
data: [20, 20, 20, 20, 20, 20, 20],
fill: false,
borderColor: 'rgb(0, 0, 0)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Min',
data: [10, 10, 10, 10, 10, 10, 10],
fill: false,
borderColor: 'red',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
},
{
label: 'Max',
data: [30, 30, 30, 30, 30, 30, 30],
fill: '-1',
borderColor: 'red',
tension: 0.1,
backgroundColor: 'rgba(255,193,8,0.5)'
},
{
label: 'Random',
data: [5, 10, 15, 20, 25, 30, 35],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
//backgroundColor: 'rgba(255,193,8,0)'
}
]
},
options: {
scales: {
y: {
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'Energy (kW)'
}
},
x: {
scaleLabel: {
display: true,
labelString: 'Time'
}
},
},
pointLabels: {
fontStyle: 'bold',
},
plugins: {
filler: {
propagate: false
}
},
}
});
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.0/chart.js" integrity="sha512-LlFvdZpYhQdASf4aZfSpmyHD6+waYVfJRwfJrBgki7/Uh+TXMLFYcKMRim65+o3lFsfk20vrK9sJDute7BUAUw==" crossorigin="anonymous"></script>
</body>