I am having trouble creating a highcharts box-plot graph, I have all the data in the correct format i.e. min, lower quartile, median, upper quartile and max.
I can display the categories but I cannot get it to display the data.
This is my code:
function BoxPlot() {
//ViewBag Variables
var Till = #Html.Raw(Json.Encode(#ViewBag.Tills));
var Per20 = #Html.Raw(Json.Encode(#ViewBag.P20));
var Per30 = #Html.Raw(Json.Encode(#ViewBag.P30));
var Per40 = #Html.Raw(Json.Encode(#ViewBag.P40));
var Per50 = #Html.Raw(Json.Encode(#ViewBag.P50));
var Per60 = #Html.Raw(Json.Encode(#ViewBag.P60));
var Per70 = #Html.Raw(Json.Encode(#ViewBag.P70));
var Per80 = #Html.Raw(Json.Encode(#ViewBag.P80));
var Per90 = #Html.Raw(Json.Encode(#ViewBag.P90));
//Combine the till no with its data
var final = [];
for(var i=0; i < Till.length; i++) {
final.push({
name: Till[i],
p20: Per20[i],
p30: Per30[i],
p40: Per40[i],
p50: Per50[i],
p60: Per60[i],
p70: Per70[i],
p80: Per80[i],
p90: Per90[i],
});
}
console.log(final)
//get the data into the correct format for box plot
var formated = [];
for(var i=0; i < final.length; i++) {
formated.push({
a: final[i].p20,
b: ((final[i].p30 + final[i].p40) / 2),
c: ((final[i].p50 + final[i].p60) / 2),
d: ((final[i].p70 + final[i].p80) / 2),
e: final[i].p90,
});
}
console.log(formated)
//graph the data
$('#container').highcharts({
chart: {
type: 'boxplot'
},
title: {
text: 'Highcharts Box Plot'
},
legend: {
enabled: true
},
xAxis: {
categories: Till,
title: {
text: 'Till No.'
}
},
yAxis: {
title: {
text: 'Value'
}
},
series: [{
name: 'Values',
data: formated,
tooltip: {
headerFormat: '<em>Till No. {point.key}</em><br/>'
}
}]
});
}
This is an example of the formatted array and the data it contains:
This is how the graph currently looks, you can see the categories array is working but it is not showing the data:
I was able to solve this by changing how I gathered the data, Im not sure if the box plot is case sensitive but by changing the variable names the data displayed
This is the whole code I am using:
function BoxPlot() {
//ViewBag Variables
var Till = #Html.Raw(Json.Encode(#ViewBag.Tills));
var Per20 = #Html.Raw(Json.Encode(#ViewBag.P20));
var Per30 = #Html.Raw(Json.Encode(#ViewBag.P30));
var Per40 = #Html.Raw(Json.Encode(#ViewBag.P40));
var Per50 = #Html.Raw(Json.Encode(#ViewBag.P50));
var Per60 = #Html.Raw(Json.Encode(#ViewBag.P60));
var Per70 = #Html.Raw(Json.Encode(#ViewBag.P70));
var Per80 = #Html.Raw(Json.Encode(#ViewBag.P80));
var Per90 = #Html.Raw(Json.Encode(#ViewBag.P90));
var heading = #Html.Raw(Json.Encode(#ViewBag.QueryTitle));
//Combine the till no with its data
var final = [];
for(var i=0; i < Till.length; i++) {
final.push({
name: Till[i],
p20: Per20[i],
p30: Per30[i],
p40: Per40[i],
p50: Per50[i],
p60: Per60[i],
p70: Per70[i],
p80: Per80[i],
p90: Per90[i],
});
}
console.log(final)
//get the data into the correct format for box plot
var formated = [];
for(var i=0; i < final.length; i++) {
formated.push({
low: final[i].p20,
q1: ((final[i].p30 + final[i].p40) / 2),
median: ((final[i].p50 + final[i].p60) / 2),
q3: ((final[i].p70 + final[i].p80) / 2),
high: final[i].p90,
});
}
console.log(formated)
var boxData = [];
//boxData.push(formated);
//console.log(boxData);
//graph the data
$('#container').highcharts({
chart: {
type: 'boxplot'
},
title: {
text: heading
},
legend: {
enabled: true
},
xAxis: {
categories: Till,
title: {
text: 'Till No.'
}
},
yAxis: {
title: {
text: 'Distribution'
}
},
series: [{
name: 'Tills',
data:
formated
}]
});
}
I'm using Highcharts.visualize to draw the graph from a table containing the data.
You can test my working code here: http://jsfiddle.net/S2XM8/1/
I have two questions:
I want to have a separate styling for my "Additional value". How do I go about it?
Can I add data for the X-axis via the javascript? For example if I need to fill in the gap between 2014-05-27 and 2014-05-25 in the table.
Highcharts.visualize = function (table, options, tableClass) {
// the categories
options.xAxis.categories = [];
$('tbody th', table).each( function () {
options.xAxis.categories.push(this.innerHTML);
});
// the data series
options.series = [];
$('tr', table).each( function (i) {
var tr = this;
$('.graph', tr).each( function (j) {
if (i === 0) { // get the name and init the series
options.series[j] = {
name: this.innerHTML,
data: []
};
} else { // add values
options.series[j].data.push(parseFloat(this.innerHTML));
console.log(this.innerHTML);
}
});
});
options.title = { text: 'Some graph' };
$('#' + tableClass + '-graph').highcharts(options);
};
var tableNumber = document.getElementById('rank-table'),
options = {
chart: {
zoomType: 'x'
},
xAxis: {
tickInterval: 30,
reversed: true,
labels: {
rotation: 45
},
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
}
},
yAxis: {
title: {
text: 'Rank'
},
min: 1,
reversed: true
},
legend: {
layout: 'vertical',
align: 'middle',
verticalAlign: 'bottom',
borderWidth: 0
}
};
Highcharts.visualize(tableNumber, options, 'number');
Both things are possible, but require to modify visualize method, see: http://jsfiddle.net/S2XM8/4/
You can set series options in a chart and then merge with data:
series: [{
// nothing special
}, {
type: 'column' // set series type for example
}]
And merging:
options.series[j] = options.series[j] || {};
options.series[j].name = this.innerHTML,
options.series[j].data = [];
Check parsed value before passing as point value:
var value = parseFloat(this.innerHTML);
if(isNaN(value)) { //null value - produces NaN when parsing
options.series[j].data.push(10);
} else {
options.series[j].data.push(value); // push value to the series
}
Trying to get some help with this weird behavior.
I managed to get the highcharts chart, multiple series etc. all setup. When using static values from a inline array, the values are assigned correctly to the chart, but if I pull the numbers out of a csv file, they are not assigned unless I pause execution with an alert message. Please see code below
$(function () {
// every row on report needs
// category defined (left side)
var mycategories = [];
// every column on report needs
// seriesname defined
var headers = [];
var myseriesnames = [];
var lines = [];
var line_tokens = [];
// Read data from csv file
$.get('top10raj.csv', function(data) {
// Split the lines
lines = data.split('\n');
console.log("First line : "+ lines[0]);
headers = lines[0].split(',');
for (var i = 1; i < headers.length; i++) {
myseriesnames.push(headers[i]);
}
//
// display all lines
//
for (var i = 1; i < lines.length; i++) {
line_tokens = lines[i].split(',');
console.log('Equip.No:' + line_tokens[0].trim()); // Equipment Number
console.log(line_tokens[1].trim()); // ActualCost
console.log(line_tokens[2].trim()); // ActualMaterial
console.log(line_tokens[3].trim()); // ActualLabor
console.log(line_tokens[4].trim()); // ActualOther
mycategories.push(line_tokens[0].trim());
}
});
alert('report ready');
var myarray = [7,6,7,8,7,8,3,4,1,4,7,8,7,5];
var serObj = [{ 'name': myseriesnames[0],
data:[8,9,8,6,5,2,3,6,5,7,4,5,8,9]
},
{ 'name': myseriesnames[1],
data:[8,5,6,9,8,7,4,5,2,5,8,7,8,6]
},
{ 'name': myseriesnames[2],
data: myarray
},
{ 'name': myseriesnames[3],
data: myarray
},
];
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
type: 'column'
},
title:{
text:'Chart Title'
},
tooltip:{
formatter:function(){
return '<b>' + this.series.name + '</b>' +
'<br/><b>Item Number:</b> ' + this.x + // X Value
'<br/><b>Amount:</b> ' + this.y + // Y Value
'<br/><b>Other Data:</b> ';// + this.point.note;
}
},
credits:{enabled:false},
legend:{
},
plotOptions: {
series: {
shadow:false,
borderWidth:0
}
},
xAxis:{
// Need to define categories for every row
// on the report (left side)
categories: mycategories,
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickLength:3,
labels: { rotation:45, align:'left'},
title:{
text:'Equipment',
}
},
yAxis:{
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickWidth:1,
tickLength:3,
gridLineColor:'#ddd',
title:{
text:'Amount (USD)',
rotation:-90,
margin:50,
}
},
series: serObj
});
});
EqptNumber,ActualTotal,ActualMaterial,ActualLabor,ActualOther,
111.3207B,666693.61,606564.37,53866.49,6262.75,
106.3355,588647.91,240175.91,322779.00,25693.00,
106.3307,364234.86,266598.36,97636.50,0,
125.L8702A,356025.49,347519.49,8506.00,0,
122.E8801A,340712.89,25483.39,33729.50,281500.00,
127.E2201,319372.29,112362.97,307731.88,100722.56,
107.3251A,310587.25,316225.36,35496.50,41134.61,
622.CW88105,307762.86,7957.36,299805.50,0,
133.1203A,307285.20,40273.19,249658.01,17354.00,
106.3352,278737.48,132009.49,146728.00,0.01,
107.3251ACC,310587.25,316225.36,35496.50,41134.61,
622.CW88105CC,307762.86,7957.36,299805.50,0,
133.1203ACC,307285.20,40273.19,249658.01,17354.00,
106.3352CC,278737.48,132009.49,146728.00,0.01,
The csv file I am using is shown at the bottom of the source.
if the following line
alert('report ready');
is commented out, I lose all the categories labels and they are replaced by 0..1,2,3.. etc. along the X-Axis. Trying hard to understand why this is happening, but so far no luck in fixing. Appreciate any help I can get with this, as I really want to use the Highcharts library with dynamic data and using only static data from predefined arrays is very limiting.
The problem is that your request for the csv file ($.get ) is executed asynchronously, meaning that the rest of your code is running before the data is returned. Try moving your code into the callback function, something like
//..your code
mycategories.push(line_tokens[0].trim());
}
//moved your code here
var myarray = [7,6,7,8,7,8,3,4,1,4,7,8,7,5];
var serObj = [{ 'name': myseriesnames[0],
data:[8,9,8,6,5,2,3,6,5,7,4,5,8,9]
},
{ 'name': myseriesnames[1],
data:[8,5,6,9,8,7,4,5,2,5,8,7,8,6]
},
{ 'name': myseriesnames[2],
data: myarray
},
{ 'name': myseriesnames[3],
data: myarray
},
];
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
type: 'column'
},
title:{
text:'Chart Title'
},
tooltip:{
formatter:function(){
return '<b>' + this.series.name + '</b>' +
'<br/><b>Item Number:</b> ' + this.x + // X Value
'<br/><b>Amount:</b> ' + this.y + // Y Value
'<br/><b>Other Data:</b> ';// + this.point.note;
}
},
credits:{enabled:false},
legend:{
},
plotOptions: {
series: {
shadow:false,
borderWidth:0
}
},
xAxis:{
// Need to define categories for every row
// on the report (left side)
categories: mycategories,
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickLength:3,
labels: { rotation:45, align:'left'},
title:{
text:'Equipment',
}
},
yAxis:{
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickWidth:1,
tickLength:3,
gridLineColor:'#ddd',
title:{
text:'Amount (USD)',
rotation:-90,
margin:50,
}
},
series: serObj
});
});
//here's where the alert used to be
///alert('report ready');
});
Here is my json data
var data = [
{"unit":"a", "status":"Stopped / Idle", "val":21.2022222222222222},
{"unit":"a", "status":"Working", "val":53.3066666666666667},
{"unit":"a", "status":"Headland Turning", "val":0.04694444444444444444},
{"unit":"a", "status":"Transport", "val":5.1425000000000000},
{"unit":"b", "status":"Stopped / Idle", "val":334.7358333333333333},
{"unit":"b", "status":"Working", "val":212.6386111111111111},
{"unit":"b", "status":"Headland Turning", "val":26.2955555555555556},
{"unit":"b", "status":"Transport", "val":0.00444444444444444444}
];
unit is the category
I want the data could be formatted in the following way so that I can plug in to series option in HighCharts:
series: [{
name: 'Stopped / Idle',
data: [21.2022222222222222, 334.7358333333333333]},
{
name: 'Working',
data: [53.3066666666666667, 212.6386111111111111]},
{
name: 'Headland Turning',
data: [0.04694444444444444444, 26.2955555555555556]},
{
name: 'Transport',
data: [5.1425000000000000, 0.00444444444444444444]}]
});
Thank you.
var data = [
{"unit":"a", "status":"Stopped / Idle", "val":21.2022222222222222},
{"unit":"a", "status":"Working", "val":53.3066666666666667},
{"unit":"a", "status":"Headland Turning", "val":0.04694444444444444444},
{"unit":"a", "status":"Transport", "val":5.1425000000000000},
{"unit":"b", "status":"Stopped / Idle", "val":334.7358333333333333},
{"unit":"b", "status":"Working", "val":212.6386111111111111},
{"unit":"b", "status":"Headland Turning", "val":26.2955555555555556},
{"unit":"b", "status":"Transport", "val":0.00444444444444444444}
];
var seriesData = [];
var xCategories = [];
var i, cat;
for(i = 0; i < data.length; i++){
cat = 'Unit ' + data[i].unit;
if(xCategories.indexOf(cat) === -1){
xCategories[xCategories.length] = cat;
}
}
for(i = 0; i < data.length; i++){
if(seriesData){
var currSeries = seriesData.filter(function(seriesObject){ return seriesObject.name == data[i].status;});
if(currSeries.length === 0){
currSeries = seriesData[seriesData.length] = {name: data[i].status, data: []};
} else {
currSeries = currSeries[0];
}
var index = currSeries.data.length;
currSeries.data[index] = data[i].val;
} else {
seriesData[0] = {name: data[i].status, data: [data[i].val]}
}
}
Now that you've seriesData and xCategories you can instantiate the chart by using something similar to
chart = new Highchart({chart: {renderTo: 'chart-div',
type: 'column'
},
plotOptions: {column: {stacking: 'normal'}},
xAxis:{ categories: xCategories},
series: seriesData
});
EDIT: Here's the jsFiddle: http://jsfiddle.net/sujay/UMeGS/
On the HighCharts website I navigated to the Demo Gallery > HighChart demos section and clicked on Stacked column on the left side of the page. From there they had a link to a JSFiddle with a demo and from there I saw two sections of code that are pertinent to you.
The first section is the xAxis property of the HighChart object. Here's what I changed it to:
xAxis: {
categories: ['Unit A', 'Unit B']
}
Those are going to be each of the columns that you are stacking the data upon.
The next section is the series property. This is where you pass in the data that you are looking to graph into those columns. It looks like this:
series: [{
name: 'Stopped / Idle',
data: [21.2022222222222222, 334.7358333333333333]
}, {
name: 'Working',
data: [53.3066666666666667, 212.6386111111111111]
}, {
name: 'Headland Turning',
data: [0.04694444444444444444, 26.2955555555555556]
}, {
name: 'Transport',
data: [5.1425000000000000, 0.00444444444444444444]
}]
In this portion you specify the name of the particular type of data and then the values for each column you specified in the xAxis property.
I played around with some of the options really quick and there is so much more that you can do with this, but here's the JSFiddle with a stacked column graph and your data.
Hope this helps!