Creating a Flot line chart with dates - javascript

I am trying to create a line chart using Flot that shows the month and year on the x axis corresponding to a number on the y axis.
Here is my code:
var data= [];
var y = 1;
var x;
var record=xmlDoc.getElementsByTagName("record");
for(i=0;i<record.length;i++)
{
x = record[i].getElementsByTagName("date_of_consent")[0].childNodes[0].nodeValue;
x = x * 1000
y = y + i;
newArray = [x, y];
data.push(newArray);
}
var dataset = [{label: "Enrollment Over Time",data: data}];
var options = {
series: {
lines: { show: true },
points: {
radius: 3,
show: false
}
}
xaxis: {
mode: "time",
timeformat: "%y/%m"
}
};
$(document).ready(function () {
$.plot($("#flot-placeholder"), dataset, options);
});
For reference the date_of_consent field has values similar to this: 1376092800000. The problem seems to be converting this number to a date. I would appreciate any suggestions. Thanks.

You have a javascript syntax error:
var options = {
series: {
lines: { show: true },
points: {
radius: 3,
show: false
}
}, <-- YOU ARE MISSING THIS COMMA!!
xaxis: {
mode: "time",
timeformat: "%y/%m"
}
};
As you code, frequently inspect the javascript console for errors.

Related

Stop Highchart when end of the Array element reached

So What I am trying to Create is a Chart in which around 130 points data are flowing in a single second time. Now, Suppose I Have an array of 1000 elements which I want to render in Highchart.
I am able to render the Highchart with the 1000 elements of array, but the problem is that after the end of the array, the Highchart is not stopping. it keeps running.
I just want to stop the Highchart when it reaches end of the array.
Here is the Code that I have tried
var data = [7,10,8,6,8,2,5,2,2,2,3,4,4,10,6,10,5,10,0,2,9,5,7,0,5,0,5,7,8,7,5,1,9,1,5,7,10,3,7,0,2,10,8,8,1,1,0,7,6,3,1,10,0,8,3,5,5,10,3,8,4,0,3,5,8,7,0,0,0,8,7,3,2,1,0,6,7,7,3,7,5,0,1,0,0,4,9,4,4,3,0,2,10,9,0,2,7,6,5,9,0,6,7,9,0,6,2,7,1,6,5,1,3,1,0,5,0,4,2,7,2,0,7,0,3,10,6,3,4,9,9,10,10,9,5,9,8,5,3,2,5,9,5,10,10,7,8,3,8,9,5,3,9,0,1,2,6,4,1,9,0,5,0,5,6,4,1,1,3,8,2,0,7,6,4,0,6,5,5,6,4,6,6,3,3,5,5,8,7,3,4,7,5,6,1,4,2,4,7,9,8,4,0,3,8,6,2,6,10,8,10,1,10,8,6,8,8,3,8,7,8,6,7,10,9,10,0,7,7,8,1,10,1,4,7,10,7,0,9,6,3,3,3,1,4,3,4,5,0,5,9,0,6,1,8,5,1,8,9,4,0,4,5,4,3,8,2,10,5,9,4,9,5,3,6,5,7,2,2,7,1,1,9,7,4,1,7,5,2,10,6,4,3,5,7,2,4,5,7,3,2,0,8,5,5,7,8,2,9,5,9,1,2,0,7,8,10,5,6,9,2,5,1,9,4,0,7,4,4,7,10,0,8,6,0,6,4,4,8,3,9,1,3,0,0,4,4,2,5,3,3,6,1,4,6,6,4,9,7,0,2,2,1,2,2,6,2,0,2,5,7,8,8,1,7,3,9,0,0,0,9,4,9,8,9,7,10,8,2,0,5,10,10,0,1,7,5,9,2,8,10,10,4,6,6,6,10,10,5,1,5,2,1,9,3,2,5,3,1,3,10,7,1,3,5,3,0,6,7,5,1,10,5,9,0,9,2,3,0,10,0,6,9,8,3,8,7,0,10,4,2,2,5,6,7,0,10,10,9,9,8,6,10,5,9,0,6,4,8,5,0,4,4,4,1,8,3,0,9,3,3,9,1,5,0,10,1,1,3,10,6,5,8,0,6,5,2,7,10,4,2,0,10,1,7,6,2,0,1,6,10,10,6,6,10,1,4,7,5,6,5,4,1,5,6,9,1,8,4,7,2,8,5,9,7,3,9,2,2,8,10,6,10,10,7,8,7,2,6,8,7,4,6,1,5,9,2,0,5,4,4,0,4,5,7,2,3,8,9,1,0,8,6,10,8,3,7,3,3,6,7,2,7,6,6,2,8,6,9,6,8,5,4,8,4,6,7,9,8,7,8,5,8,2,0,8,5,0,5,2,8,4,7,0,7,1,4,8,10,8,2,5,10,9,1,9,3,0,6,9,2,10,5,1,4,0,4,9,1,1,3,5,0,5,5,2,5,1,1,7,0,2,6,8,10,7,9,3,0,9,4,2,4,6,2,2,9,2,7,3,6,6,9,2,2,0,2,9,1,5,7,10,10,1,8,5,9,9,4,1,7,1,0,0,6,7,7,7,2,9,9,2,10,5,4,2,3,10,9,9,7,1,1,6,8,4,9,6,7,4,9,4,2,7,6,2,6,0,1,5,5,8,9,5,1,7,8,7,3,2,3,1,1,2,5,6,4,10,8,10,3,3,1,0,6,7,0,7,4,8,4,7,6,0,7,1,2,3,10,4,1,10,7,9,4,7,7,10,10,10,6,8,9,7,3,10,9,0,3,6,2,10,5,3,6,8,5,0,2,3,1,6,9,10,9,10,7,5,8,7,4,4,3,10,2,3,4,3,10,8,5,9,8,5,6,2,4,9,1,5,0,7,1,1,4,4,10,4,7,8,8,9,7,1,9,5,5,4,3,0,0,9,5,6,3,3,4,6,1,2,6,2,8,4,10,0,9,1,10,2,7,3,6,3,9,2,3,5,7,8,1,1,9,3,4,6,7,6,2,2,8,0,10,3,3,5,7,4,1,3,9,5,4,3,3,2,9,8,7,8,7,6,8,7,7,1,2,10,10,2,9,3,2,3,2,9,9,0,3,0,4,9,6,0,1,6,9,5,8,7,9,5,6,8,3,5,3,4,9,8,0,3,4,8,6,9,4,7,1,9,8,0,4,8,1,0,7,3,3,1,6,9,9,5,4,3,8,8,9,10,4,9,0,7,8,6,9,8,4,10,4,1,2,5,4,0,6,4,1];
var json_array = data ;
var i = 0;
function next() {
return json_array[i++];
// i++;
}
Highcharts.chart('container', {
chart: {
type: 'line',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0],
chart = this;
var count = 0 ;
setInterval(function() {
var x = (new Date()).getTime(), // current time
y =next();
console.log(y) ;
series.addPoint([x, y], false, true);
chart.redraw(false);
}, 1000/130);
}
}
},
time: {
useUTC: false
},
title: {
text: 'ECG Graph Plot From MySQl Data'
},
xAxis: {
type: 'datetime',
labels: {
enabled: false
},
tickPixelInterval: 150
},
yAxis: {
//max: 1.5,
//min: -1.5,
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
headerFormat: '<b>{series.name}</b><br/>',
pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
animation: false,
name: 'ECG Graph Plot From MySQl Data',
dataGrouping: {
enabled: false
},
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -1000 ; i <= 0; i += 1) {
data.push([
time + i * 10,
null
]);
}
return data;
}())
}]
});
I Have also created a Fiddle for it as you can see below.
https://jsfiddle.net/abnitchauhan/toqaxLj7/
Just clear Interval when it reached the last element of the array. check out following code.
var draw = setInterval(function() {
var x = (new Date()).getTime(), // current time
y =next();
console.log(y) ;
if (i == data.length) {
clearInterval(draw);
return;
}
series.addPoint([x, y], false, true);
chart.redraw(false);
}, 1000/130);
here is the fiddle code link.
https://jsfiddle.net/geekcode/8nL53x01/1/

How can I graph two sensor data values with Highcharts?

I have some data that I'm graphing with Highcharts, which I was able to set up by using a modified version of some demo code. The graph works fine when I graph some data from a sensor. The relevant section of my code looks like this:
<script>
Highcharts.stockChart('container', {
chart: {
backgroundColor:'transparent',
events: {
load: function() {
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(),
y = Number(getTemp());
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
xAxis: {
type: 'datetime',
labels: {
style: {
},
},
tickPixelInterval: 200,
},
yAxis: {
type: 'linear',
labels: {
y: 5,
style: {
},
},
},
series: [{
name: 'Temperature',
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -200; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: 0
});
}
return data;
}())
}]
});
</script>
Now I want to add a second sensor reading using a similar function "getTemp2()" on the same graph as a second series. When I try to edit the code in the "series" data section, I get a blank graph (meaning it fails to load correctly). I believe the code in the "series" section populates the graph with zeros (for y values) across the entire chart. But I'm not sure if I need to add both something in the "events" section, the "series" section, or both? Can someone tell me how I can add a second sensor reading to this chart? Here is what I tried that failed:
events: {
load: function() {
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(),
y = Number(getTemp());
series.addPoint([x, y], true, true);
},
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(),
y = Number(getTemp2());
series.addPoint([x, y], true, true);
}, 1000);
}
First of all, you need to create two series in a chart configuration object:
Highcharts.stockChart('container', {
...,
series: [{
data: getData()
}, {
data: getData()
}]
});
Then, in load event you can use addPoint method on both of the series:
chart: {
events: {
load: function() {
var series1 = this.series[0],
series2 = this.series[1];
setInterval(function() {
var x = (new Date()).getTime(),
y1 = Number(getTemp()),
y2 = Number(getTemp2());
series1.addPoint([x, y1], false, true);
series2.addPoint([x, y2], true, true);
}, 1000);
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/nk4yawzt/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
Docs: https://www.highcharts.com/docs/chart-concepts/series

Chart Js - Group(average) y axis values against same x axis in line/scatter chart

I have datasets with x, y values x denotes date y denotes values.and i have successfully generated a chart. look at the pic attached below
I'm using this code to generate the chart (generated using the above chart)
var config = {
type: 'scatter',
data: {
//labels: this.HoursStrings,
datasets: [{
data: yserires, // example data [{x:2019/01/02,y:12},{x:2019/01/02,y:12}}]
fill: true,
borderColor: "#3e82f7",
yAxesGroup: "1"
}]
},
options: {
responsive: true,
title: {
display: false,
},
legend: {
display: false
},
showLines: true,
tooltips: {
mode: 'index',
intersect: true,
callbacks: {
label: function (tooltipItem, data) {
var value = data.datasets[0].data[tooltipItem.index];
var day = moment(new Date(value.x)).format(self.timeformat);
var point = value.y + " " + self.unityType
return point;
}
} //
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
type: 'time',
time: {
unit: self.timeUnit
},
ticks: {
beginAtZero: true
}
}],
yAxes: [{
display: true,
ticks: {
beginAtZero: true,
userCallback: function (value, index, values) {
return self.roundValues(value) + " " + self.unityType
}
}
}]
},
elements: {
line: {
tension: .1, // bezier curves
}
}
}
};
setTimeout(() => {
var ctx = document.getElementById("canvas");
this.chart = new Chart(ctx, config);
this.chart.update()
}, 50)
Expected Result
how can group different y-axis values against the same x-axis values (should be one single value like the average of y-axis) is there any build in functions available in chart js or I need to group those value before binding the chart.
Note: The date should be grouped (averaged) by day/hour/week/month
like below image
You can preprocess your array getting the mean value from the data before feeding it to the graph:
// Your data array
let array = [{ x: '2019/01/02', y: 12 }, { x: '2019/01/02', y: 13 }]
// The output data for Chart js
var output = [];
// Get the non-unique values and add them to an array
array.forEach(function (item) {
var existing = output.filter(function (v, i) {
return v.x == item.x;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
if (!Array.isArray(output[existingIndex].y))
output[existingIndex].y = [output[existingIndex].y]
output[existingIndex].y = output[existingIndex].y.concat(item.y);
} else {
if (typeof item.value == 'string')
item.value = [item.value];
output.push(item);
}
});
// Compute the mean
console.dir(output.map(val => {
val.y = (val.y).reduce((a, b) => a + b, 0) / (val.y).length
return val
}));
I am not familiar with chart js, but from my experience with D3 and time series visualization in general, the result you are seeing is the expected behavior. I.e. the time series visualization is constructed as a continuous line intersecting all data points, in the order the data points are specified.
So to answer your question about grouping, I would say yes, you need to group the data yourself before creating a chart.
First, however, you need to consider what grouping means - is it an average, a sum, a minimum, a maximum, or something different. I'm guessing you'll want an average, but it will depend on your use case and analysis needs.
I've written a short bit of code, that groups an array of entries by calculating the average of reoccurring x values:
const data = [
{ x: '2019/01/28', y: 19 },
{ x: '2019/01/29', y: 15 },
{ x: '2019/02/02', y: 12 },
{ x: '2019/02/02', y: 13 },
{ x: '2019/02/02', y: 14 },
{ x: '2019/02/02', y: 15 },
{ x: '2019/02/02', y: 18 },
{ x: '2019/02/02', y: 21 },
]
const dataGrouper = {}
data.forEach((dataPoint) => {
if (!dataGrouper[dataPoint.x]) {
dataGrouper[dataPoint.x] = []
}
dataGrouper[dataPoint.x].push(dataPoint)
})
const groupedData = []
Object.keys(dataGrouper).forEach((groupingKey) => {
const sum = dataGrouper[groupingKey].reduce((accumulator, currentValue) => {
return accumulator + currentValue.y
}, 0)
groupedData.push({
x: groupingKey,
y: sum / dataGrouper[groupingKey].length
})
})
console.log({groupedData})

put your own series in highcharts sereis

I am trying to pass in my_series to series in highcharts to graph stacked bars. From my php, I get hash, which is like this:
{"Oat":{"10":"AA","11":"H"},"Brown Rice":{"10":"AA","11":"BB"}}
I actually dont know what is wrong with my code. I think it should work, but when I run it, I do not see anything on the screen. I checked that sample_name has "Oat" and "Brown Rice", which is what I want.
What I eventually want is a color-coded stacked bar graph that has samples on the yAxis and position on the xAxis. I think I almost got to what I want, it's just a problem with making an actual graph.
Thank you!
$(function() {
var allele_str = [];
var sample_name = [];
var hash = {};
var my_series = {
data: []
};
var position = [];
var options = {
chart: {
renderTo: 'container',
defaultSeriesType: 'bar',
zoomType: 'xy',
inverted: true
},
title: {
text: 'Gene'
},
xAxis: {
categories: [],
},
legend: {
enabled: false
},
yAxis: {
title: {
text: 'Position'
},
labels: {
enabled: false
}
}
plotOptions: {
series: {
stacking: 'normal'
}
}
series: []
};
$.getJSON('6K_load.php', function(data) {
sample_name = Object.keys(data);
options.xAxis.categories.push(sample_name);
for (var x in sample_name) { // sample Oat, BR
for (var k in data[sample_name[x]]) { // pos
series.name = k;
var z = data[sample_name[x]][k];
hash[z] = 1;
allele_str.y = hash[z];
if (z === 'AA') {
allele_str.color = 'grey';
}
if (z === 'BB') {
allele_str.color = 'blue';
}
if (z === '--') {
allele_str.color = 'white';
}
if (z === 'H') {
allele_str.color = 'red';
}
my_series.data.push(allele_str);
}
options.series.push(my_series);
}
var chart = new Highcharts.Chart(options);
});
});
The problem is that you not parse your data to number value, you need to use parseFloat() in this line
my_series.data.push(parseFloat(allele_str));

Adding series dynamically in highcharts

(function($){
$(function () {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var i=0;
var chart = new Highcharts.Chart({
chart: {
type: 'spline',
renderTo: 'container',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var Name = new Array();
Name[0] = "Random data";
Name[1] = "Volvo";
var length=chart.series.length;
var flag=0;
var index=0;
var x = (new Date()).getTime(), // current time
y = Math.random();
for (var k=0;k<Name.length;k++) {
for(var j=0;j<chart.series.length;j++) {
if(chart.series[j].name==Name[k]) {
flag=1;
index=j;
x = (new Date()).getTime();
y = Math.random();
break;
}
}
if(flag==1) {
chart.series[index].addPoint([x, y], true, true);
flag=0;
} else {
chart.addSeries({name: '' + Name[k] + '', data: [] });
chart.series[length].addPoint([x, y+1], true);
length=length+1;
}
}
}, 1000);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
})()
}]
});
});
});
})(jQuery);
I am able to add series and add point in charts but the series that I add after initialization, which is "volvo", is not drawing lines between its points. What might be the problem?
And is there any other way of comparing arrays and adding points without a for-loop? Because I can get millions of series at times and I don't want to be looping over arrays to check if it exists or not. So is there any efficient way of finding wheteher a list already exists, and if it does what is its index?
here is its fiddle: www.jsfiddle.net/2jYLz/
It is related with fact that you have enabled shifting in addPoint() when you add new serie. In other words, shifting remove first point and add new in the end of serie. So when you have one point it caused your scenario. So you need to disable shipfing, and when lenght of series.data achieve i.e 10 points, shifting should be enabled.

Categories