Highcharts sets default value for blank data - javascript

How to set/supply value (default to 0) for blank data in hours as shown in attached image below.
The target result should have all graphs even for blank hours.

You can create a loop and add points to your data array with some default y value (50 in the example below) and x value with the same interval as tickInterval:
var data = [
[1561593600000, 102.5],
[1561658400000, 177.45],
[1561723200000, 115.5]
],
interval = 2 * 60 * 60 * 1000,
j = 1,
i = data[0][0] + interval;
for (j; j < data.length; j++) {
for (i; i < data[j][0]; i += interval) {
data.push([i, 50])
}
i += interval;
}
Highcharts.chart('container', {
chart: {
type: 'column'
},
series: [{
data: data.sort(function(a, b) {
return a[0] - b[0]
})
}],
xAxis: {
type: 'datetime',
tickInterval: interval
},
});
Live demo: http://jsfiddle.net/BlackLabel/m0zfeyd4/

Related

how to get dynamic step size in react-chartjs-2

I am using Chart.js to draw graphs in typescript.
I want to get a dynamic weight and bring a minimum and a maximum. And with maxTicksLimit as 5, I want to keep 5 Ticks no matter what data comes in.
The decimal point of body weight is taken to the first decimal point.
ex) 50.3
I want to show the difference between minimum and maximum as much as possible.
please help me!!!
ex1) maximum weight: 74.5, minimum weight: 71
result
Y Axis maximum weight: 76 , Y Axis minimum weight: 71
ex1 result image
enter image description here
ex2) maximum weight: 76.9, minimum weight: 62
result
Y Axis maximum weight: 76 , Y Axis minimum weight: 61
ex2 result image
enter image description here
The beforeBuildTicks callback also works to create a dynamic tick step size. Here is the code:
{
maintainAspectRatio: false,
tooltips: {
mode: 'label',
position: 'nearest',
},
scales: {
xAxes:[
{...}
],
yAxes: [
{
position: 'left',
id: 'y-axis-0',
scaleLabel: {
display: true,
labelString: 'label string goes here',
fontSize: 16,
},
ticks: {
beginAtZero: true,
stepSize: .25,
},
beforeBuildTicks: function(axis) {
if (axis.max >= 17) {
axis.options.ticks.stepSize = 1;
} else if (axis.max >= 10) {
axis.options.ticks.stepSize = .5;
}
}
}
]
}
}
I solved this problem in the following way.
There was a callback function of afterBuildTicks in chart.js
※ chart.js documents link.
It becomes possible to customize the ticks.
//... middle code skip
const getChartMaxAndMin = (
maxValue,
minValue
): { max: number; min: number } => {
// Convert all decimal places to integers
let max = Math.ceil(maxValue);
let min = Math.floor(minValue);
// a multiple of 5
const MULTIPLES = 5;
const DIVIDED_REMAINING_VALUE_LIMIT = 3;
// Maximum to Minimum difference
const diff = max - min;
const diffDividedRemainingValue = diff % MULTIPLES;
const remainingValue =
MULTIPLES *
(diffDividedRemainingValue > DIVIDED_REMAINING_VALUE_LIMIT
? Math.floor(diff / MULTIPLES) + 2
: Math.floor(diff / MULTIPLES) + 1) -
diff;
if (remainingValue % 2 !== 0) {
max = max + Math.floor(remainingValue / 2) * 2;
min = min - Math.floor(remainingValue % 2);
return { max, min };
}
max = max + remainingValue / 2;
min = min - remainingValue / 2;
return { max, min };
};
const customizedAxesTicks = (axis) => {
const EQUAL_PARTS = 5; // set 5 parts
const max = axis.max;
const min = axis.min;
const steps = (max - min) / EQUAL_PARTS;
const ticks = [];
for (let i = min; i <= max; i += steps) {
ticks.push(i);
}
axis.ticks = ticks;
return;
};
const {max, min} = getChartMaxAndMin(68,57);
const chartOptions = {
//... code skip
scales: {
yAxes: [
{
//... code skip
ticks: {
max: max,
min: min
},
afterBuildTicks: customizedAxesTicks,
//... code skip
};
I would appreciate it if you could let me know if there is a better way😀

Spurious point is being added in the end C3 charts

I'm using C3 charts library to draw charts. I send data to the chart using two arrays, which are 'timeArray' and 'dataArray', one for the X-Axis and the other one for Y-Axis respectively. This simple logic was working fine.
Later I had to implement a change such that I had to take average of every three elements of an array and then make a new array and then plot the graph using averaged values.
I started facing a problem that a spurious point was being plotted on the graph. Whenever this error occurs, only one spurious point is added in the end. I've checked the arrays that are used to plot the graph, they do not have that spurious point. When I take the average of every three elements, I face this problem almost every time, however when I take average of 500 or 1000 points I face this error only sometimes.
As you can see in the code I have already tried removing the last point of the final array since the spurious point that was being added was always the last point in the chart. I've also tried changing the graph type, it did not help.
socket.on('get-avg-graph', function(data) {
// dataPoints = Points for Y-Axis
// mili = Points for X-Axis
var dataPoints = data.dataPoints;
var mili = data.mili;
var sumX = 0;
var sumY = 0;
var avgXGraph = 0;
var avgYGraph = 0;
var avgXArray = [];
var avgYArray = [];
for (var i = 0; i < dataPoints.length - 999; i++) {
for (var j = i; j < i + 999; j++) {
sumX = sumX + mili[j];
sumY = sumY + dataPoints[j];
}
if (sumY !== 0) {
avgXGraph = ( sumX / 1000 );
avgXArray.push(avgXGraph);
avgYGraph = ( sumY / 1000 );
avgYArray.push(avgYGraph);
sumX = 0;
sumY = 0;
avgXGraph = 0;
avgYGraph = 0;
}
}
io.emit('get-avg-graph-response', avgXArray, avgYArray);
});
socket.on('get-avg-graph-response', function(avgXArray, avgYArray) {
plot_X_axis = [];
plot_Y_axis = [];
drawChart();
avgXArray.splice( -1, 1);
avgYArray.splice( -1, 1);
plot_X_axis.push.apply(plot_X_axis, avgXArray);
plot_Y_axis.push.apply(plot_Y_axis, avgYArray);
drawChart();
});
function drawChart() {
var graphTitle = $("#test_type_show").val();
dataArray = [];
dataArray[0] = "PRESSURE";
dataArray.push.apply(dataArray, plot_Y_axis);
timeArray = [];
timeArray[0] = "TIME";
timeArray.push.apply(timeArray, plot_X_axis);
if (chart==null) {
chart = c3.generate({
bindto: '#chart1',
title: {
text: graphTitle
},
data: {
x: 'TIME',
columns: [
timeArray,
dataArray
],
type: 'spline'
},
axis: {
x: {show:false},
y: {show: true}
},
grid: {
x: {
show: true
},
y: {
show: true
}
},
point: {
show: false
}
});
} else {
chart.load({
x: 'TIME',
columns: [
timeArray,
dataArray
],
type: 'spline'
});
}
chart.internal.xAxis.g.attr('transform', "translate(0," + chart.internal.y(0) + ")");
chart.internal.yAxis.g.attr('transform', "translate(" + chart.internal.x(0) + ", 0)");
}
I expect the output of the code to be the actual graph without any spurious data added anywhere.

Start live Flot Chart at 0

I have a Flot Chart that is live and generates random numbers that displays on the chart. It is used only as a dummy so I don't need real live data. I want the chart to start at 0 on yaxis and 100 on xaxis to make it look as real as possible. Below is my code in the js file.
var data = [], totalPoints = 100
h = 0
function getRandomData() {
//h = h + 1
//return h
//data.push(h)
if (data.length > 0)
data = data.slice(1)
// Do a random walk
while (data.length < totalPoints) {
var prev = data.length > 0 ? data[data.length - 1] : 50,
y = prev + Math.random() * 10 - 5,
if (y < 0) {
y = 0
} else if (y > 100) {
y = 100
}
data.push(y)
}
// Zip the generated y values with the x values
var res = []
for (var i = 0; i < data.length; ++i) {
res.push([i, data[i]])
}
return res
}
var interactive_plot = $.plot('#interactive', [getRandomData()], {
grid : {
borderColor: '#f3f3f3',
borderWidth: 1,
tickColor : '#f3f3f3'
},
series: {
shadowSize: 0, // Drawing is faster without shadows
color : '#3c8dbc'
},
lines : {
fill : true, //Converts the line chart to area chart
color: '#3c8dbc'
},
yaxis : {
min : 0,
max : 100,
show: true
},
xaxis : {
show: true
}
})
var updateInterval = 500 //Fetch data ever x milliseconds
var realtime = 'on' //If == to on then fetch data every x seconds. else stop fetching
function update() {
interactive_plot.setData([getRandomData()])
// Since the axes don't change, we don't need to call plot.setupGrid()
interactive_plot.draw()
if (realtime === 'on')
setTimeout(update, updateInterval)
}
//INITIALIZE REALTIME DATA FETCHING
if (realtime === 'on') {
update()
}
//REALTIME TOGGLE
$('#realtime .btn').click(function () {
if ($(this).data('toggle') === 'on') {
realtime = 'on'
}
else {
realtime = 'off'
}
update()
})
/*
* END INTERACTIVE CHART
*/
There is a button that calls the Flot chart into action and it works great but it looks too much like a staged chart. I need it start at 0 on the y-axis and 100 on the x-axis. Any information on how to go about this would be great and very much appreciated.
Fill your data array with zeroes before you start, then your update function starts adding random points one at a time instead of starting with 100 random data points:
for (var i = 0; i < totalPoints; i++) {
data.push(0);
}
See this fiddle for a full example.
PS: Please end your code lines with a semicolon!

jqxChart with relative values

I was playing around with the waterfall series of the jqxChart.
According to its API, the following piece of code defines the values of the axis, in this case it's the y-axis:
valueAxis:
{
title: {text: 'Population<br>'},
unitInterval: 1000000,
labels:
{
formatFunction: function (value) {
return value / 1000000 + ' M';
}
}
}
Is it possible to define the intervals not with absolute values, but with relative values. So that the interval are e.g. 10% and the overall value is 100%?
Simply doing unitInterval: '10%' doesn't work.
This is how it should look like:
Here is a fiddle.
I think you're looking for these options :
logarithmicScale: true,
logarithmicScaleBase: 1.10,
Example:
valueAxis:
{
title: {text: 'Population<br>'},
logarithmicScale: true,
logarithmicScaleBase: 1.10,
labels:
{
formatFunction: function (value) {
return value / 1000000 + ' M';
}
}
},
Edit:
var accuracy = 2;
var first = data[0].population;
var last = data[data.length - 2].population;
var unit = (100 / last);
// convert raw data to differences
for (var i = 0; i < data.length - 2; i++)
data[i].population = (data[i].population * unit).toFixed(accuracy);

Google Chart 2 Lines with not the same number of data

I'm trying to create a dynamic Google Chart line.
I have 2 lines in a range of a day (from 00h00 to 23h50 - 0am to 12pm) with a point for each lines every 10 minutes (00h00, 00h10, 00h20 etc...).
So for each lines I have 144 values for a day (1*6*24 - 6 / hours because I have 1 every 10 minutes).
For the first line, I have all the values at the start of the day (144 values) but for the other one, I'm drawing it according the current hour (exemple if it's 01:00 - 1am, I have only 6 values).
So i'm trying to draw the lines but I have a problem if my secondes lines doesn't have 144 values.
Here is the function to draw the chart with the different lines
function drawChart(chart_div) {
var data = get_data();
var chart = new google.visualization.ComboChart(document.getElementById(chart_div));
chart.draw(data, {
height: 300,
width: 1000,
chartArea:{left:40,top:5,width:"100%",height:"80%"},
seriesType: 'line',
series: {
0: {
color: '#0080FF'
},
1: {
color: '#bdbdbd',
enableInteractivity: false
}
},
tooltip: {
isHtml: true
},
legend: {
position: 'none'
},
vAxis: {
gridlines: {
color: '#e5e5e1'
}
},
hAxis: {
viewWindow: {
min: 0,
max: 144
},
ticks: [0, 24, 48, 72, 96, 120, 144] // display labels every 24
}
});}
Here is the code to launch the function to draw the chart
google.load('visualization', '1', {'packages':['corechart']});
google.setOnLoadCallback(function() {
drawChart("chart_one");
});
And here is the function to generate the data (They are currently randomly generate but I'll take them from DB later)
function get_data(){
var data = new google.visualization.DataTable();
data.addColumn('string', 'Time');
data.addColumn('number', 'Heartbeat (%)');
data.addColumn('number', 'Heartbeat moy (%)');
var total = 0;
for(i = 0; i < 24; i++){
for(j=0; j <= 5; j++){
var num = "";
if(i < 10){
num += "0";
}
if(total < 98){
data.addRows([[num + i + "h"+j+"0", Math.floor((Math.random() * 10) + 91), Math.floor((Math.random() * 10) + 91)]]);
} else {
data.addRows([[num + i + "h"+j+"0", "", Math.floor((Math.random() * 10) + 91)]]);
}
total++;
}
}
return data;
}
So basically I would have something like that :
But if I'm setting the secondes line values to "", it say
Error: Type mismatch. Value does not match type number in column index 2
Does anyone have any idea how to bypass the value for the seconde lines if I doesn't have it ?
Use null instead of an empty string "" for points that don't have any data

Categories

Resources