change format of X axis in c3.js chart - javascript

I am generating a c3.js chart with the folling JSON and code, I'm trying to change the format of the X axis dates like this "November 2016" "N16". Can I get some help with this please? Thanks!
response = [["November 2016","December 2016","January 2017","February 2017","March 2017","April 2017"],["total"
,2,43,60,51,46,110],["mammo",1,20,34,12,12,60],["face",1,20,16,30,32,32],["body",0,3,10,9,2,18],["photo"
,0,19,27,12,5,21],["scan",2,24,33,39,41,89]]
initMonthlyUsageChart(response);
function initMonthlyUsageChart(amounts) {
var months = amounts.shift();
c3.generate({
bindto: '#monthly_usage_chart-js',
data: { columns : amounts },
axis: {
x: {
type: 'category',
categories: months,
tick: {
rotate: 90,
format: function (x) { // x comes in as a time string.
x[0] = x[0].map(function(date) {
return date.replace(/^(\w{1}).*(\d{2})$/gi, "$1$2");
});
}
}
}
}
});
}

x doesn't come in as a time string, it comes in as an index to the category
Therefore, change to this bit of code to do what you need:
format: function (x) { // x comes in as an index
return months[x].replace(/^(\w{1}).*(\d{2})$/gi, "$1$2");
}

This approach may helps to format categorical chart tick formatting :
var config = bindto: '#monthly_usage_chart-js',
data: { columns : amounts },
axis: {
x: {
type: 'category',
categories: months,
tick: {
rotate: 90,
format: function (x) { // x comes in as a time string.
x[0] = x[0].map(function(date) {
return date.replace(/^(\w{1}).*(\d{2})$/gi, "$1$2");
});
}
}
}
};
config.axis.x.tick = {
format : function(x) {
var desiredValue = config.axis.x.categories[x];//'cause x here is a key for category chart
return desiredValue.replace(/^(\w{1}).*(\d{2})$/gi, "$1$2");//apply your formatting stuff
}
};
var chart = c3.generate(config);

Related

dynamically adding series to highcharts

I'm relative new to highcharts so I'm not that knowledgeable.
But what I am trying to do is that I am trying to dynamically create series with a name and some x, y values. To get the x and y values I use two dictionaries looking like this:
The X values. They are dates
The Y values. They are seconds
What I want to do is create a series that have the names of the keys and then they can have multiple points for x, y values.
So for example at "Fiber_Mätning" I have two values in the key in both dictionaries. What I want to do is that I create a series with the name "Fiber_Mätning", and then it should have two points where I give both x and y value.
So the 1st point in "Fiber_Mätning" would be x:"2020-10-28" y:"28800"
and the 2nd point in "Fiber_Mätning" would be x:"2020-10-29" y:"18000"
After that I would move on onto the next key in both dictionaries and do the same. So the way I create the series need to be a function that is dynamically creating series and the points depending on the amount of keys and values in the dictionaries.
Currently my highchart code looks like this:
$('#container').highcharts({
chart:{
type: 'column',
events:{
load: function(){
RedrawColumns(this)
},
redraw: function(){
RedrawColumns(this)
}
}
},
title:{
text: 'Time worked by {{user_to_show}}'
},
subtitle:{
text:'{{user_to_show}}´s flex time: '
},
tooltip:{
formatter: function (){
var text = 'Date: ' + this.x + '<br>' + 'Time: ' + secondsTimeSpanToHMS(this.y/1000) +
'<br>' +'Extra info:' + {{extra_info|safe}}[this.x];
return text;
}
},
xAxis:
{
categories: {{all_dates|safe}}
},
yAxis:
[{
title:
{
text: '' //If it isnt given '' it will display "value" so using '' to hide it
},
gridLineWidth: 1,
type: 'datetime', //y-axis will be in milliseconds
dateTimeLabelFormats:
{ //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
opposite: true
}],
plotOptions:
{
series:
{
dataLabels:
{
enabled: true,
formatter: function()
{
if( this.series.index == 0 )
{
return secondsTimeSpanToHMS(this.y/1000) ;
}
else
{
return this.y;
}
}
}
}
},
series:
[{
}]
});
});
(I am doing this with django, html and js)
If anything is unclear please say so and I will try to explain it in further detail.
Thanks in advance for any replies.
Here is my proposal for the solution. I think that everything is explained in the comments. If something is unclear, feel free to ask.
let data1 = {
Jarnvag_asdasd: ['2020-10-22'],
Fiber_Matning: ['2020-10-28', '2020-10-29'],
Fiber_Forarbete: ['2020-10-28', '2020-10-29'],
};
let data2 = {
Jarnvag_asdasd: [28800],
Fiber_Matning: [28800, 18000],
Fiber_Forarbete: [28800, 14400],
};
// The constructor to create the series structure
function CreateSeries(name, data) {
this.name = name;
this.data = data;
}
// series array
let series = [];
// Iterate through the data to concat them
for (let i in data1) {
let data = [];
data1[i].forEach((d, j) => {
data.push([d, data2[i][j]])
})
series.push(new CreateSeries(i, data))
}
Highcharts.chart('container', {
series: series
});
Demo: https://jsfiddle.net/BlackLabel/r7ame5gw/

JSON api timestamp + data parsing

I'm making a chart using Highcharts.js
The API I'm using has a different output than what Highchart uses.
Highchart reads JSON data as [timestamp, data]
which looks something like this: [1512000000000,171.85],
furthermore, the rest of the data is parsed within the same call.
Now MY Api outputs data by a single call for each timestamp (via url &ts=1511929853 for example
outputs {"ENJ":{"USD":0.02154}} (the price for that point in time)
Now here's where things get complicated. I would need to parse the price from a certain date, till now.
I've already made a ++ variable for the timestamp, but how would I include the timestamp and the price for that timestamp within the array for the data output.
It's a bit confusing, as the calls would have to be repeated so many times to draw a historical graph of the price. Some help would be appreciated. If you need more clarification, I'm right here.
Data is parsed via data function
full code here
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime()/1000);
function count() {
if (startDate != endDate) {
startDate++
}
else {
return false;
}
};
count();
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function (data) {
// Create the chart
var enjPrice = `${data.ENJ.USD}`;
console.log(enjPrice);
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data: JSON.parse("[" + enjPrice + "]"),
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
});
You can use spread operator, like this,
let var = [new Date().getTime(), { ...data }.ENJ.USD]
This will result [1512000000000, 171.85] as you expected.
You need to make different functions for getting the data and generating the chart. Below is an example of how would you do it.
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime() / 1000);
var data = [];
function count() {
if (startDate != endDate) {
data.push(getPrice(startDate));
startDate++;
} else {
generateChart();
}
};
count();
function getPrice(timestamp) {
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function(data) {
return [timestamp, data.ENJ.USD];
});
}
function generateChart() {
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data,
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
}
Though this is not the best way how you would do it but you get an idea.
I managed to solve the problem, by using a different API, which indexes data for past 30 days. I iterated into each index, 31, of them and grabbed the time and high(price) values and parsed them into a number since I was getting a "string" and then looped them into an array and put them into the final data [array]. just what I needed for the chart to work. If anyone needs any help just ask away. :) PS: Excuse the console.logs as I was using them to debug and test which helped me tremendously, you can remove them, as shall I
$.getJSON('https://min-api.cryptocompare.com/data/histoday?fsym=ENJ&tsym=USD', function(data) {
var x = `${data.Data[0].time}`;
var y = `${data.Data[0].high}`;
console.log(x);
console.log(y);
var tempData = [];
console.log(tempData);
for (var i = 0; i < 31; i++ ) {
var a = `${data.Data[i].time}`;
var b = `${data.Data[i].high}`;
function numberfy(val){
parseFloat(val);
}
a = parseFloat(a);
a = a * 1000;
b = parseFloat(b);
x = [a , b];
tempData.push(x);
};
data = tempData;
console.log(data.length);
Highcharts.stockChart('container', {

On C3js, how to make the tooltip on a bar chart display the data for just that bar as you hover over it?

I have the following chart using C3.js and some JSON data. How can I make the tooltip display each individual bar's data, and not all the bars data on a table?
var chart = [
{'0-9': 249.8740575482693,
'10-19': 238.2744788358169,
'20-29': 369.10362988529357,
'30-39': 156.9635033529556,
'40-49': 266.00448275832673,
'50-59': 283.5138392550998,
'60-69': 211.16877917295733,
'70-79': 154.08326897057742,
'80+': 148.8063871481496},
]
chart = c3.generate({
bindto: '#chart',
data: {
json: chart,
keys: {
value: ['0-9', '10-19', '20-29', '30-39', '40-49', '50-59', '60-69', '70-79', '80+']
},
type: 'bar'
},
color: {
pattern: ['#E39920', '#53B5B5', '#CD249A', '#F56223', '#6FAAD6','#A33E54', '#27668D','#75AB36', '#6E37B6']
},
tooltip: {
format: {
title: function (d) { return 'Data'},
value: function (value, ratio, id) {
var format = id === 'data1' ? d3.format(',') : d3.format('$');
return format(value);
}
}
}
});
You can use grouped: false to separate out the values of the tooltip so they display only what you have moused over, like so:
tooltip: {
grouped: false,
format: {
title: function (d) { return 'Data'},
value: function (value, ratio, id) {
var format = id === 'data1' ? d3.format(',') : d3.format('$');
return format(value);
}
}
}
By default, c3 groups tooltip values together, and this option separates them :)

Show only the MIN/MAX value on Y-AXIS with C3JS

I would like to have the y-axis only with the min/max values of my data.
I tried to use the d3 directive but without results.
I had a look at google but I didn't find an answer to achieve this behaviour.
Below the code:
$.getJSON('assets/json/chartc3.json', function(data)
{
scene=data;
var chart = c3.generate({
bindto: '#chartc3',
data:
{
json: scene,
keys:
{
x: 'round',
value: ['Marketable', 'Total Requested Capacity', 'Your Bid'],
},
types: {
Marketable: 'area'
},
colors: {
Marketable: '#A09FA2',
'Total Requested Capacity': '#272E80',
'Your Bid': '#8EBF60'
}
},
axis:
{
x: {
tick:
{
culling:
{
max: 10
}
},
type: 'category'
},
y:
{
min: 0,
padding : {
bottom : 0
},
tick:
{
values: [[0], [***d3.max(scene)]***],
format: function (d) { return d3.format(',f')(d) +' kWh/h' }
//or format: function (d) { return '$' + d; }
}
}
}.........
How could I achieve the result described above ? d3.max(scene) returns NaN.
Well the problem is scene is not an array its a json object.
var k = d3.max([1,5,2])
k will be 5
so you will need to pass an array of elements which constitute your y ordinals.
you need to use
d3.max(arr, function(d){return numberic value});
or
var arr = scene.map(function(d){return ...the number value..})
y:{
min:d3.min(arr),
max:d3.max(arr)
},
the function depends on the array element of your data.
I used a little function to calculate the max by myself.
var maxs=0;
for (var j=0; j<scene.length; j++) {
var maxtemp=Math.max(scene[j].Marketable, scene[j]['Your Bid'], scene[j]['Total Requested Capacity']);
maxs=Math.max(maxs, maxtemp);
}

How to format Highcharts columnRange to get json data for temperature Min and Max

I'm trying to display information on Highcharts from the forecast.io api. With the help of others on this site, I have figured out how to call the data using a simple line or area chart; however, I can't figure out how to with the columnRange chart. I want to display the daily min and max temperature forecast. So the top column would display today's min and max temp, and the next column would be tomorrows, and so on.
To call the min and max for today from forecast.io:
data.daily.data[0].temperatureMin
data.daily.data[0].temperatureMax
Tomorrows would have a "1" instead of a 0. The day after would have a "2".
I haven't been able to figure out how to make a function that does this for each day. I have a jsfiddile which includes my forecast.io API key. This is needed to call from the source.
Anyways, any help would be much appreciated! http://jsfiddle.net/nn51895/gjw9m1qo/2/
(my x axis labels are really messed up as you will see..)
$(function () {
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true
},
title: {
text: ''
},
subtitle: {
text: ''
},
xAxis: {
},
yAxis: {
title: {
text: ''
}
},
tooltip: {
valueSuffix: '°F'
},
plotOptions: {
columnrange: {
dataLabels: {
enabled: true,
formatter: function () {
return this.y + '°F';
}
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Daily Min and Max',
data: 'ChartData',
pointStart: new Date().getTime(),
pointInterval:90000000,
}]
});
});
$.ajax({
url: "https://api.forecast.io/forecast/87a7dd82a91b0b765d2576872f2a3826/53.479324,-2.248485",
jsonp: "callback",
dataType: "jsonp",
success: function(chart) {
var dataArr = new Array();
var height = chart.xAxis[0].height;
var pointRange = chart.daily.data[0].temperatureMax - chart.daily.data[0].temperatureMin;
var max = chart.daily.data[0].temperatureMax;
var min = chart.daily.data[0].temperatureMin;
var pointCount = (max - min) / pointRange;
var timeint = chart.daily.data[0].time;
for(var i=0; i<chart.daily.data.length; i++)
dataArr.push(chart.daily.data[i].temperatureMin);
plotChart(dataArr, timeint)
}
});
First of all, as said in the comment:
success: function (chart) {
...
var height = chart.xAxis[0].height;
}
You are trying to get for some unknown reason height of xAxis from the chart. Meanwhile you chart variable is referring to the data from AJAX call. I hope that's clear, so remove that line or change to:
success: function (chart) {
var myChart = $('#container').highcharts();
var dataArr = new Array();
var height = myChart.xAxis[0].height;
}
Second thing, that option:
data: 'ChartData',
Is wrong, there should be an empty array, since Highcharts requires array for data, not some string:
data: [],
Now, after fixing these bugs, you should go to this demo and create the same data format. That's example for required format for Highcharts.
More about series.data can be found in API reference - you need to read this.

Categories

Resources