Data aggregation in c3js - json

Is there an option to aggregate the data in C3 charts? When the JSON contains multiple data elements with the same category, data is plotted as multiple points in the charts, where as it should be aggregated and shown as a single point in the chart.
Attached are the C3 charts and expected chart format.
In the example: "name 1" show a single point at 300 as upload, where as ion C3 it show one point at 200 and the other at 100 for the same.
Code Used:
var chart = c3.generate({
bindto:'#png-container',
data: {
json: [
{name: 'name1', upload: 200, download: 200, total: 400},
{name: 'name1', upload: 100, download: 300, total: 400},
{name: 'name2', upload: 300, download: 200, total: 500},
{name: 'name3', upload: 400, download: 100, total: 500},
],
keys: {
x: 'name', // it's possible to specify 'x' when category axis
value: ['upload', 'download'],
},
groups: [
['name']
]
},
axis: {
x: {
type: 'category'
}
}
});
Output of the above code:
Expected Output:

Not built into c3 as far as i'm aware. You can use d3's nest operator to aggregate the json data before passing it to c3 though.
var json = [
{name: 'name1', upload: 200, download: 200, total: 400},
{name: 'name1', upload: 100, download: 300, total: 400},
{name: 'name2', upload: 300, download: 200, total: 500},
{name: 'name3', upload: 400, download: 100, total: 500},
];
var agg = function (json, nestField) {
var nested_data = d3.nest()
.key(function(d) { return d[nestField]; })
.rollup(function(leaves) {
// Work out the fields we're not nesting by
var keys = d3.merge (leaves.map (function(leaf) { return d3.keys(leaf); }));
var keySet = d3.set(keys);
keySet.remove (nestField);
var dataFields = keySet.values();
// total these fields up
// console.log(leaves, dataFields); // just for testing
var obj = {};
dataFields.forEach (function (dfield) {
obj[dfield] = d3.sum(leaves, function(d) {return d[dfield];});
});
return obj;
})
.entries(json);
// return to original json format
var final_data = nested_data.map (function(nestd) {
nestd.values[nestField] = nestd.key;
return nestd.values;
});
return final_data;
};
var chart = c3.generate({
bindto:'#png-container',
data: {
json: agg(json, "name"),
keys: {
x: 'name', // it's possible to specify 'x' when category axis
value: ['upload', 'download'],
},
groups: [
['name']
]
},
axis: {
x: {
type: 'category'
}
}
});
https://jsfiddle.net/8uofn7pL/2/
whoops, linked to the wrong fiddle there

Related

ApexChart diagram in Vuejs including ApiEndPoint

How can I fetch data from a JSON API using the following code:
var options = {
chart: {
type: "bar",
},
series: [
{
name: "Bitcoin",
data: [],
},
],
xaxis: {
categories: [5, 30, 60],
},
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
I want data() to return the following amountList array, which contains numbers inside:
function data() {
return {
apiEndPoint: "https://api.coinbase.com/v2/prices/spot?currency=",
apiData: [],
amountList: [],
};
};

Echarts - Dynamic multi line chart based on Json data

I am trying to plot time line chart with multiple lines (number of lines is dynamic based on Json data). I am getting Json data as mentioned. I would like to have each line plotted for each product. How should I convert data so that echarts supports?
[
{date: "2019-05-21 00:00:00 UTC", value: 100, product: 'p1'},
{date: "2019-05-21 00:00:00 UTC", value: 50, product: 'p2'},
{date: "2019-05-19 00:00:00 UTC", value: 200, product: 'p3'},
{date: "2019-05-18 00:00:00 UTC", value: 70, product: 'p1'},
{date: "2019-05-18 00:00:00 UTC", value: 125, product: 'p2'},
{date: "2019-05-18 00:00:00 UTC", value: 55, product: 'p3'}
]
You should be storing your axis data separately from your values, in a simple multi-line chart: see the following two examples:
https://echarts.baidu.com/echarts2/doc/example/line1.html#-en
https://echarts.baidu.com/echarts2/doc/example/line8.html#-en
The second example provides the "time" x-axis type, which we can use with the first, which provides a good multi-line framework.
Your option may look something like this:
option = {
title : {
text: 'Multi-line Time Axis example',
subtext: 'made for Dileep'
},
tooltip : {
trigger: 'axis'
},
toolbox: {
show : true,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {show: true, type: ['line', 'bar']},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : [
{
type : 'time',
}
],
yAxis : [
{
type : 'value',
axisLabel : {
formatter: '{value} $'
}
}
],
series : [
{
name: 'series1', // Product p1, for instance
type: 'line',
data: (function () {
var d = [];
var len = 0;
var now = new Date();
var value;
while (len++ < 10) {
d.push([
new Date(2014, 9, 1, 0, len * 10000), // some Date() object
(Math.random()*30).toFixed(2) - 0// // some random value
]);
}
return d;
})()
},
{
name: 'series2', // product p2
type: 'line',
data: (function () {
var d = [];
var len = 0;
var now = new Date();
var value;
while (len++ < 10) {
d.push([
new Date(2014, 9, 1, 0, len * 10000),
(Math.random()*30).toFixed(2) - 0,
]);
}
return d;
})()
}
]
};

Highcharts - how change JSON to csv

I have a small problem...
$(function () {
$.get('../../../abc-test.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
]);
}
$('#test').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
//csv: document.getElementById('csv').innerHTML
},
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
abc-test.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
Why this code dont't work ?
Don't work:
- Two panes, candlestick and volume
- OHLC
- 1.7 million points with async loading...
The issue is in the "date" in csv or something else ... ?

Highcharts stacked bar data from CSV

I'm trying to implement a stacked bar chart with data coming from a CSV.
I need to update series: with the data from the CSV file which contains, for example "John,10,5,3,4,1".
Help please!
$(function () {
$('#container').highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Stacked bar chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
}
},
legend: {
reversed: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
});
UPDT
I finally got it working, but still there's a problem. The bars are inverted and I need them to be exactly in the same order as in the CSV file.
Here's my parser:
$.get('chart.csv', function(data) {
var lines=data.split('\n');
$.each(lines, function(lineNo, line) {
var items = line.split(',');
var series = {
data: []
};
$.each(items, function(itemNo, item) {
if (itemNo == 0) {
series.name = item;
} else {
series.data.push(parseFloat(item));
}
});
options.series.push(series);
});
var chart = new Highcharts.Chart(options);
The contents of the CSV file:
Disconnection,30,30
Site Care,12,12
Documentation,35,35
Lining,22,22
Connection,70,52
I need the stacked bars in the same order as in the legend:
http://i.stack.imgur.com/6EkHg.png
You could try to custom setting the series indices before you render the chart to fix the inversion of the bars.
Something like this might do the trick:
for (var i = 0; i < options.series.length; i++) {
options.series[i].index = options.series.length - 1 - i;
options.series[i].legendIndex = i;
}

Highcharts bargraph from json data in angularJS

I have a highcharts bargraph whose values are received from json whose format is as follows:
"bargraph":
[
{
"categories": "['S', 'M', 'T', 'W', 'T', 'F']",
"series1": "[800, 1100, 80, 1800, 1600, 2000]",
"series2": "[800, 1100, 80, 1800, 1200, 800]"
}
]
How can i embed those values for my bargraph in angularJS
HTML Code:
<div id="bargraph" bargraph={{bargraph}}><\div>
Directive:
angular.module('example').directive('bargraph', function () {
element.highcharts({
xAxis: [
{
categories: [] //embed categories value here
},
series: [
{
name: 'series1',
data: [] //Embed series1 data here
},
{
name: 'series2',
data: [] //Embed series2 data here
}
]
})
})
Please provide a suitable way to embed the data from json.
Here is a directive i copied and pasted from my webapp it is how i render highcharts using a directive NOTE: not all of this directive is applicable to you and some of it is specific to what i needed but you get the idea.
lrApp.directive('chart', function () {
return {
restrict: 'E',
template: '<div></div>',
transclude: true,
replace: true,
link: function (scope, element, attrs) {
var chart = null;
var chartsDefaults = {
chart: {
renderTo: element[0],
type: attrs.type || null,
height: attrs.height || null,
width: attrs.width || null,
},
colors: scope.$eval(attrs.colors) || null,
title: {
style: {
display: 'none'
}
},
xAxis: {
//categories: ['{"-7 days"|date_format}','{"-6 days"|date_format}','{"-5 days"|date_format}','{"-4 days"|date_format}', '{"-3 days"|date_format}', '{"-2 days"|date_format}', '{"-1 day"|date_format}', '{$smarty.now|date_format}'],
categories: scope.$eval(attrs.dates) || null,
gridLineDashStyle: 'ShortDot',
gridLineColor: "#C0C0C0",
gridLineWidth: 1,
labels: {
y: 27
}
},
yAxis: {
title: {
text: null
},
min: 0,
gridLineDashStyle: 'ShortDot',
gridLineColor: "#C0C0C0",
gridLineWidth: 1
},
credits: {
enabled: false
},
legend: {
enabled: false
},
plotOptions: {
series: {
shadow: false,
lineWidth: 3
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
this.x + ': ' + this.y + '</b>';
}
}
};
//Update when charts data changes
scope.$watch(attrs.value, function (newVal, oldVal) {
if (!newVal.length) return;
// We need deep copy in order to NOT override original chart object.
// This allows us to override chart data member and still the keep
// our original renderTo will be the same
var deepCopy = true;
var newSettings = {};
chartsDefaults.series = newVal;
chartsDefaults.colors = scope.$eval(attrs.colors);
chartsDefaults.xAxis.categories = scope.$eval(attrs.dates);
console.log(chartsDefaults);
chart = new Highcharts.Chart(chartsDefaults);
});
}
}
});
and this is how it used it obviously you would change "line" to bar:
<chart value="stats.sets" dates="stats.days" colors="stats.colors" type="line"></chart>