How to format my json data for stack column chart in HighCharts - javascript

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!

Related

Highcharts Remote Data - JSON Object Undefined

I'm trying to render a Highcharts column chart from MySQL data -> json_encode() -> getJSON(). 95% of the time there are 6 rows of data to process, so this can be easily looped through manually and the chart renders fine. The problem is when there are occasionally fewer rows in the results array - I am of course seeing TypeError: Cannot read property 'name' of undefined in these cases.
My working code:
$.getJSON(url, function(json)) {
if(typeof json === 'object' && json.length > 0) {
var nameData = [json[0]['name'],json[1]['name'],json[2]['name'],json[3]['name'],json[4]['name'],json[5]['name']];
var matchedData = [json[0]['data']['Matched'],json[1]['data']['Matched'],json[2]['data']['Matched'],json[3]['data']['Matched'],json[4]['data']['Matched'],json[5]['data']['Matched']];
var bookedData = [json[0]['data']['Booked'],json[1]['data']['Booked'],json[2]['data']['Booked'],json[3]['data']['Booked'],json[4]['data']['Booked'],json[5]['data']['Booked']];
}
var options = {
chart: {
renderTo: 'div',
type: 'column'
},
title: {
text: 'Chart Title',
x: -20
},
xAxis: {
type: 'category',
categories: nameData,
crosshair: true
},
series: [{
name: 'Matched',
data: matchedData
}, {
name: 'Booked',
data: bookedData
}]
}
chart = new Highcharts.Chart(options);
}
This renders the chart correctly. However when there are fewer than the usual 6 items in the array, the TypeError stops things.
I attempted this to count the array items prior to sending to Highcharts:
var nameData = [];
var matchedData = [];
var bookedData = [];
if (typeof json === 'object' && json.length > 0) {
for (var a = 0; a < json.length; a++) {
nameData += [json[a]['name']+","];
matchedData += [json[a]['data']['Matched']+","];
bookedData += [json[a]['data']['Booked']+","];
}
}
This alerts() out the same results as the manually-created array, but nothing renders on the chart. What needs to change?
Try mapping over your data. You can set everything really easily using the map function. It's a lot cleaner and simpler as well. You can find a reference for map here.
$.getJSON(url, function(json)) {
if(typeof json === 'object' && json.length > 0) {
var nameData = json.map(obj => obj['name']);
var matchedData = json.map(obj => obj['data']['Matched']);
var bookedData = json.map(obj => obj['data']['Booked']);
}
var options = {
chart: {
renderTo: 'div',
type: 'column'
},
title: {
text: 'Chart Title',
x: -20
},
xAxis: {
type: 'category',
categories: nameData,
crosshair: true
},
series: [{
name: 'Matched',
data: matchedData
}, {
name: 'Booked',
data: bookedData
}]
}
chart = new Highcharts.Chart(options);
}

Highcharts Using CSV instead of JSON

I tried the code like this with many small restructuration and modification but without success.
Here is the code:
$(function () {
$.get('data.csv', function(data) {
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length,
// set the allowed units for data grouping
groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]],
i = 0;
for (i; i < dataLength; i += 1) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
]);
}
$('#chart').highcharts({
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
labels: {
align: 'right',
x: -3
},
title: {
text: 'OHLC'
},
height: '60%',
lineWidth: 2
}, {
labels: {
align: 'right',
x: -3
},
title: {
text: 'Volume'
},
top: '65%',
height: '35%',
offset: 0,
lineWidth: 2
}],
data: {
csv: data
},
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
Here is data.csv:
Date,Open,High,Low,Close,Volume
2013-12-20,9371.08,9413.09,9352.98,9400.18,161686900
2013-12-19,9279.68,9351.9,9257.24,9335.74,98276500
2013-12-18,9145.35,9190.73,9122.05,9181.75,82342700
2013-12-17,9142.75,9161.8,9085.12,9085.12,72207500
2013-12-16,9004.62,9187.78,8997.75,9163.56,99105600
2013-12-13,9016.78,9046.63,8990.58,9006.46,67761700
2013-12-12,9032.67,9060.54,8984.28,9017,75120200
2013-12-11,9093.26,9153.14,9065.51,9077.11,64845800
2013-12-10,9180.29,9223.73,9091.97,9114.44,74363400
Can you help me to figure out the problem or purpose new approch please ?
What is my goal ?
Is to be able to load a CSV file inside the chart instead of using JSON file.
Why ?
Because modifing CSV file is more easier for me using PHP than JSON, and it's for performance too.
Thank's
When you do data.length, you are getting length of the csv file string. What you need to do is split the data with the newline delimiter.
// sample from data
var data = `Date,Open,High,Low,Close,Volume
2013-12-20,9371.08,9413.09,9352.98,9400.18,161686900
2013-12-19,9279.68,9351.9,9257.24,9335.74,98276500`;
// split by \n (new line)
data = data.split('\n'); // now data is an array of rows
var finalObj = [];
// iterate over the rows
data.map(function(row){
var obj = {};
// row is a string separated by ','
row = row.split(','); // now row is an array
obj['date'] = row[0];
obj['open'] = row[1];
obj['high'] = row[2];
obj['low'] = row[3];
obj['close'] = row[4];
obj['volume'] = row[5];
finalObj.push(obj);
})
console.log(finalObj);
Output:
[
{
date:'Date',
open:'Open',
high:'High',
low:'Low',
close:'Close',
volume:'Volume'
},
{
date:'2013-12-20',
open:'9371.08',
high:'9413.09',
low:'9352.98',
close:'9400.18',
volume:'161686900'
},
{
date:'2013-12-19',
open:'9279.68',
high:'9351.9',
low:'9257.24',
close:'9335.74',
volume:'98276500'
}
]

HighChart - accessing series data by category name

The question is simple. How do I programmatically edit data series which corresponds to desired_category_name in this Fiddle ?
$(function() {
var chart, x,
btnRemove = $('#remove'),
btnAdd = $('#add'),
btnEdit = $('#edit');
x = 10;
btnAdd.click(function() {
chart.series[0].addPoint(Math.floor(Math.random() * 10 + 1)); // Return random integer between 1 and 10.
});
btnEdit.click(function() {
desired_category_name = 'USA'
// Do something like chart.series[0].data[i].update(x += 10);
});
btnRemove.click(function() {
if (chart.series[0].points[0]) {
chart.series[0].points[0].remove();
}
});
$('#container').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: 'No data in pie chart'
},
series: [{
type: 'pie',
name: 'Random data',
data: [
['USA', 1],
['Europe', 2]
]
}]
});
chart = $('#container').highcharts();
});
You can access series data with this - it has an array of points:
chart.series[0]
You can modify point with this:
chart.series[0].data[0].update( _new_value_ )
Each point has an attribute "name" that corresponds to category.
chart.series[0].data[0].name // USA
http://jsfiddle.net/3nhm9cjc/
$('#edit').click(function() {
desired_category_name = 'USA';
// Do something like chart.series[0].data[i].update(x += 10);
console.log(chart.series[0].data.length)
for(var i = 0; i< chart.series[0].data.length; i++){
if(chart.series[0].data[i].name===desired_category_name){
chart.series[0].data[i].update(10);
}
}
});

JavaScript - Highcharts box plot not displaying

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
}]
});
}

Highcharts grouped categories data csv

Hello together I have this example bar chart:
As you can see it has grouped categories
Now I want to be able to import the data through csv or xml.
I came across the data module of highcharts, but this is not designed for grouped categories I think.
What I achieved until now was this:
HTML Head:
<script type="text/javascript" src="jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="highcharts.js"></script>
<script type="text/javascript" src="exporting.js"></script>
<script type="text/javascript" src="grouped-categories.js"></script>
<script type="text/javascript" src="data.js"></script>
<script type="text/javascript">
$.get('data.csv', function(csv) {
$('#container').highcharts({
chart: {
type: 'bar'
},
data: {
csv: csv,
itemDelimiter: ';'
},
title: {
text: 'Roadmap'
},
yAxis: {
title: {
text: 'Date'
},
labels: {
style: {
fontSize: '12px'
}
},
type: 'datetime',
min : Date.UTC(2015, 10, 1),
max : Date.UTC(2021, 01, 1),
tickInterval: 30.41667 * 24 * 3600 * 1000
}
});
});
</script>
This generates this bar chart:
Out of this csv:
Category,Date
Task 1,1483138800000
Task 2,1457046000000
Task 1,1467237600000
Task 1,1483138800000
Is it possible to generate a grouped categories bar chart out of csv or xml?
I was thinking about something like this:
Project1; Phase 1; Task 1, Value
Project1; Phase 2; Task 1, Value
Project1; Phase 2; Task 2, Value
Project1; Phase 3; Task 1, Value
An then try to get this output so highcharts can work with it:
categories: [{
name: "Project 1",
categories: [{
name: "Phase 1",
categories: ["Task 1"]
}, {
name: "Phase 2",
categories: ["Task 1"]
}, {
name: "Phase 3",
categories: ["Task 1", "Tas k2"]
}]
Grouped Categories plugin expects format of categories that is not supported directly by Highcharts. Data module is Highcharts official plugin, so it will not work like that by default or by using some available settings. Parsing CSV data - creating series data array and categories object could be the way to resolve the problem.
Here is example of what that parser might look like: http://jsfiddle.net/vboak5hr/
$.get('data.csv', function(data) {
// Split the lines
var lines = data.split('\n');
var series = [];
// Iterate over the lines and add categories or series
$.each(lines, function(lineNo, line) {
var items = line.split(';'),
hasThisCategory = false,
categoryIndex = -1,
categoryPath = options.xAxis.categories;
//add data point to series data
options.series[0].data.push(parseInt(items[3]));
// I. level of categories
Highcharts.each(categoryPath, function(category, i) {
if (category.name === items[0]) {
hasThisCategory = true;
categoryIndex = i;
}
});
if (!hasThisCategory) {
categoryPath.push({
name: items[0],
categories: []
});
}
if (categoryIndex === -1) categoryIndex = categoryPath.length - 1;
// II. level of categories
categoryPath = categoryPath[categoryIndex].categories;
hasThisCategory = false;
categoryIndex = -1;
Highcharts.each(categoryPath, function(category, i) {
if (category.name === items[1]) {
hasThisCategory = true;
categoryIndex = i;
}
});
if (!hasThisCategory) {
categoryPath.push({
name: items[1],
categories: []
});
}
if (categoryIndex === -1) categoryIndex = categoryPath.length - 1;
// III. level of categories
categoryPath = categoryPath[categoryIndex].categories;
hasThisCategory = false;
categoryIndex = -1;
Highcharts.each(categoryPath, function(category, i) {
if (category === items[2]) {
hasThisCategory = true;
}
});
if (!hasThisCategory) {
categoryPath.push(items[2]);
}
});
// Create the chart
var chart = new Highcharts.Chart(options);
});

Categories

Resources