I am learning to create a stacked bar/column chart using highcharts. The json data i have from a pojo class has three properties- date, status and count. On a given day i could have no records for a particular status or more than one record too. This is how JSON looks:
[{"dateV":"2015-11-16","status":"A","count":10},{"dateV":"2015-11-16","status":"B","count":15},{"dateV":"2015-11-15","status":"A","count":5},{"dateV":"2015-11-14","status":"A","count":10},{"dateV":"2015-11-14","status":"B","count":10},{"dateV":"2015-11-14","status":"C","count":10}]
This data is in an arraylist right now. Date is the key here.X axis on the graph would have the date. Y axis should show all the status values stacked. I am able to create the graph but it is completely wrong and i think i know why. I am not grouping the data properly. I have created multiple series - 1 for category, and 1 each for different status values. Considering this is how i am populating the chart, how should i create the category and data series?
var categData = [];
var statusACountData = [];
var statusBCountData = [];
$.getJSON(url, function(response) {
$.each(response, function(i, item) {
var dateVal=response[i].dateV;
var statusVal=response[i].status;
var countVal=response[i].count;
console.log(dateVal+"-"+statusVal+"-"+countVal);
******LOGIC TO CREATE SERIES*****
});
$('#chartDiv').highcharts({
chart : {
type : 'column'
},
title : {
useHTML: true,
text : '<h3>StackedChart</h3>'
},
xAxis : {
categories : categData ,
crosshair : true
},
yAxis: {
allowDecimals: false,
min: 0,
title: {
text: 'Count'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series : [ {
name : 'A',
data : statusACountData
},{
name: 'B',
data : statusBCountData //This may increase.Lets consider i have only two status values.
} ]
});
});
CODEPEN: http://codepen.io/anon/pen/MKreQE
Your problem is filtering and mapping, here something that you can improve on to get you started:
var filterMap = function (arr, status) {
return arr.filter(function(a) { return a.status === status; }).map(function(a) { return [status, a.count]; })
};
$.getJSON(url, function(response) {
$('#chartDiv').highcharts({
chart : {
type : 'column'
},
title : {
useHTML: true,
text : '<h3>StackedChart</h3>'
},
xAxis : {
categories : categData ,
crosshair : true
},
yAxis: {
allowDecimals: false,
min: 0,
title: {
text: 'Count'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series : [ {
name : 'A',
data : filterMap(response, 'A')
},{
name: 'B',
data : filterMap(response, 'B')
} ]
});
});
This should be the required result.
Try the example below, where xAxis has dateValue and yAxis has countVal and statusVal. Don't forget to link to your jsonfile (in my case I use jsonfile.json):
var dateVal=[];
var statusVal=[];
var countVal=[];
$.getJSON("jsonfile.json", function(response) {
$.each(response, function(i, item) {
dateVal[i]=response[i].dateV;
statusVal[i]=response[i].status;
countVal[i]=response[i].count;
console.log(dateVal+"-"+statusVal+"-"+countVal);
});
$('#chartDiv').highcharts({
chart : {
type : 'column'
},
title : {
useHTML: true,
text : '<h3>StackedChart</h3>'
},
xAxis : {
categories : dateVal ,
crosshair : true
},
yAxis: {
allowDecimals: false,
min: 0,
title: {
text: 'Count'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series : [ {
name : 'A',
//data : statusACountData
data:statusVal,
},{
name: 'B',
//data : statusBCountData //This may increase.Lets consider i have only two status values.
data: countVal,
} ]
});
});
Related
I have one Json with multiple array and foreach array I want to create Pie chart, but I don't know how to do it.
This is the array thet I have. And this is what I tried :
function Pie() {
$.getJSON("/Admin/Attivita/OreOggi", function (data) {
console.log(data);
var oreTecico = [];
var oreTecico = [];
var oreMalatia = [];
var oreStraordinario = [];
var oreInfortunio = [];
var oreFerie = [];
for (var i = 0; i < data.length; i++) {
nomeTecnico.push(data[i].nome);
oreTecico.push(data[i].odinario);
oreMalatia.push(data[i].malatia);
oreStraordinario.push(data[i].straordinario);
oreInfortunio.push(data[i].infortunio);
oreFerie.push(data[i].ferie);
};
// Build the chart
Highcharts.chart('zdravko', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'Ore segnate oggi'
},
tooltip: {
pointFormat: '<b>{point.name}</b>: {point.y:.1f} h.'
},
accessibility: {
point: {
valueSuffix: '%'
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
name: nomeTecnico[0],
colorByPoint: true,
data: [{
name: '',
y:0,
sliced: true,
selected: true
}, {
name: 'Odinario',
y: oreTecico[0]
}, {
name: 'Malatia',
y: oreMalatia[0]
}, {
name: 'Straordinario',
y: oreStraordinario[0]
}, {
name: 'Infortunio',
y: oreInfortunio[0]
}, {
name: 'Ferie',
y: oreFerie[0]
}]
}]
});
});
}
It shows only the last "data". I want to make fo each array one pie. If i have 100 arrays I want 100 pies.
UPDATE:
I added this :
data.forEach(function (el) {
var chartData = [el.data1, el.data2];
var chartContainer = document.createElement('div');
document.getElementById('zdravko').append(chartContainer);
Highcharts.chart(chartContainer, {
series: [{
type: 'pie',
data: chartData
}]
});
});
The chartData is array of undefined objects.
Is it possible to make for or foreach inside Highcharts?
You need to use the Highcharts.chart method in a loop, for example:
var data = [{
data1: 12,
data2: 25
}, {
data1: 67,
data2: 11
}];
data.forEach(function(el) {
var chartData = [el.data1, el.data2];
var chartContainer = document.createElement('div');
document.getElementById('container').append(chartContainer);
Highcharts.chart(chartContainer, {
series: [{
type: 'pie',
data: chartData
}]
});
});
Live demo: http://jsfiddle.net/BlackLabel/x95pbw7j/
API Reference: https://api.highcharts.com/class-reference/Highcharts#.chart
I am facing an issue to add the dynamic value in Highcharts Jquery. I have two arrays like name and value
name/categoryname - ["ZYG", "BLA", "GAS", "LBE", "LIM", "EMB", "NAU"]
value/basevalue - [483.7932253,601.125844,680.2910403,886.7269613,548.3400347,630.8979143,0]
face the issue in passing the base value in. I tried to pass the value in the array and string type. The issue is not solved yet.
I used the bar chart to display. The coding is here. Normally coding works fine. The issue faced when I use dynamic value.
function displaychart(obj)
{
var categoryname = [];
$.each(obj['name'], function( key, value ) {
categoryname.push(value);
});
var ybasevalue = "[";
$.each(obj['basevalue'], function( key, value ) {
ybasevalue += value + ",";
});
ybasevalue += "]";
Highcharts.chart('container'+i, {
chart: {
type: 'bar'
},
title: {
text: 'Protein Sequence'
},
subtitle: {
text: 'Source'
},
xAxis: {
categories: categoryname,
title: {
text: null
}
},
yAxis: {
min: 0,
title: {
text: 'Proteomics',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
valueSuffix: ''
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: 0,
y: 180,
floating: true,
borderWidth: 1,
backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
shadow: true
},
credits: {
enabled: false
},
series:[
{
name: 'Protein',
data: ybasevalue
},
]
});
}
}
I pass an array of Strings instead of an array of Numbers. Values inside single or double quotes are Strings in JavaScript.
So I use
var ybasevalue = [];
$.each(obj[i]['basevalue'], function( key, value ) {
ybasevalue.push(parseInt(value)); });
Got a column called ChartData in database with a string value of 4,11,25,36,50. Trying to assign this value to a hidden variable so JS can read the value of this and put this value in the data option using high charts. I have console.log the variable and looks like its appearing as a string rather than an array when being parsed across the server side to the client side.
C# code
string str = reader["ChartData"].ToString();
string[] strList = str.Split(','); //seperate the hobbies by comma
// convert it in json
dataStr = JsonConvert.SerializeObject(strList, Formatting.None);
hiddenvariable.Value = dataStr;
JS code:
function CreateBoxPlot() {
var hv = $('#hiddenvariable').val();
alert(hv); //["40","61","65","74","77"]
var chart;
var titleText = 'Test Chart Title';
var subTitleText = 'Test Chart Subtitle';
var type = 'boxplot';
var data = hv;
console.log(data); //["40","61","65","74","77"]
$(function () {
$('#container').highcharts({
chart: { type: type, inverted: true },
title: { text: titleText },
subtitle: { text: subTitleText },
legend: { enabled: false },
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
pointWidth: 50
}
},
xAxis: {
visible: false
},
yAxis: {
visible: true,
title: {
text: 'Values'
},
plotLines: [{
value: 80,
color: 'red',
width: 2
}]
}
});
chart = $('#container').highcharts();
chart.addSeries({ data: data });
});
}
However when i hardcode data to the below value this works. How do i format this correctly when its parsed over to the JS side:
var data = [[40,61,65,74,77]]
You have to convert the string '["40","61","65","74","77"]' to js array with numbers. To make it work on each browser you can follow this approach:
Parse the string to js array using JSON.parse()
Loop through the created array and convert each element to number:
var json = '["40","61","65","74","77"]',
dataString = JSON.parse(json),
data = [],
i;
for (i = 0; i < dataString.length; i++) {
data[i] = +dataString[i];
}
Code:
$(function() {
var json = '["40","61","65","74","77"]',
dataString = JSON.parse(json),
data = [],
i;
for (i = 0; i < dataString.length; i++) {
data[i] = +dataString[i];
}
$('#container').highcharts({
chart: {
inverted: true
},
legend: {
enabled: false
},
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
pointWidth: 50
}
},
xAxis: {
visible: false
},
yAxis: {
visible: true,
title: {
text: 'Values'
},
plotLines: [{
value: 80,
color: 'red',
width: 2
}]
}
});
chart = $('#container').highcharts();
chart.addSeries({
data: data
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/ay1xmgoc/
Taking reference from the comments, add this to your code and then try.
var data = hv.map(function (element) {
return +element;
});
I am having trouble parsing data into a flot chart. I am unsure if it is the way I am using $.each to build my data arrays. I figured I could Anyone know what's wrong?
UPDATED: correct link:
http://jsfiddle.net/qxdgrozs/
This is my json object and js code:
$(function () {
var jsonString = JSON.parse(readJSON('[
{
"Person":"Fred",
"NetIncome":0,
"StateTax":0,
"FedTax":0,
"TotalTax":0,
"AvgTaxRate":0
},
{
"Person":"Alex",
"NetIncome":5555385.06,
"StateTax":124463.24,
"FedTax":4320151.7,
"TotalTax":4444614.94,
"AvgTaxRate":44.45
},
{
"Person":"John",
"NetIncome":5555180.86,
"StateTax":124667.44,
"FedTax":4320151.7,
"TotalTax":4444819.14,
"AvgTaxRate":44.45
}
]';
var myData = JSON.parse(jsonString);
var data1 = [];
var data2 = [];
$.each(myData, function(i, jti) {
data1[i] = {
label: jti.Person,
data: jti.StateTax
}
data2[i] = {
label: jti.Person,
data: jti.FedTax
}
}
$.plot("#placeholder", [{
data: data1,
label: "test",
bars: {
show: true,
barWidth: 0.4,
align: "left"
}
}, {
data: data2,
label: "flot bug serie",
bars: {
show: true,
barWidth: 0.4,
align: "right"
}
}], {
series: {
bars: {
show: true,
barWidth: 0.6,
align: "center"
}
},
xaxis: {
mode: "categories",
tickLength: 0
},
grid: { hoverable: true, clickable: true }
});
});
I have also tired using the push method with no avail.
After fixing a lot of syntax errors, the big issue is that flot needs one array per datapoint, not an object, change
$.each(myData, function(i, jti) {
data1[i] = {
label: jti.Person,
data: jti.StateTax
}
data2[i] = {
label: jti.Person,
data: jti.FedTax
}
}
to
$.each(myData, function(i, jti) {
data1.push([jti.Person, jti.StateTax]);
data2.push([jti.Person, jti.FedTax]);
});
See this fiddle for the working code.
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
}