Chart.js point format data for a scatter plot - javascript

Chart.js scatter chart only accepts data in a point format (x, y). Im a trying to fill the data points with infomration about medications from a file called meds.json
More specifically, the x would be the month of last fill date of the medication and the y would be the dose.
How can I grab all this data from the meds.json file and insert it to the data to create the points for my scatter plot?
If I try to grab all dates and store them in an array, and all the dose values in another array, how can I use that populate the point data using those arrays?
Here's how to make a scatter plot using Chart.js, I am trying to populate the x,y points under data 'data':
// charts.js
var scatterChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{
// x = month, y = dose
// fill these in for all meds in the json file
x: -10,
y: 0
}, {
x: 0,
y: 10
}, {
x: 10,
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'top'
}]
}
}
});
}
meds.json
[
{
"name": "Simvastatin",
"dose": 10,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
},
{
"name": "Lisinopril",
"dose": 5,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
}
...... The list goes on
]

You should actually use a line chart for this which would be much more appropriate and exactly show the trend & relationship between month and the dosage.
But since you asked for scatter chart...you can do it like this :
const data = [{
"name": "Simvastatin",
"dose": 10,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
},
{
"name": "Lisinopril",
"dose": 5,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
}
]
const transformedData = data.map(obj=>{
return {
x:new Date(obj["last fill date"]).getMonth() + 1,
y:obj.dose,
}
})
console.log(transformedData)
and then use as
var scatterChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: 'Scatter Dataset',
data: transformedData
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'top'
}]
}
}
});
}
Hope this helps !

Related

How make more advanced charts in node-red? How can I make live chart in Node-red with two or more y axis?

I have problem with make more advanced live chart. I use node-red on PC to collect data from PLC and display it in line chart using standard node-red dashboard chart node. PLC read values from 30 sensors: 20 preassure, 3 temperature, 3 flow, 1 speed. Read frequency is 4Hz. Not all values are visible at time, because I want chart to be clear. For this I need also split y axis according to sensors. So one for preassure, one for temperature, one for flow and one for speed. For now data is coming in form of array msg.payload[] but it is not important because I will format data to proper form. I know format data for live chart to work is
{topic:"temperature", payload:22}
{topic:"humidity", payload:66}
and for static chart
msg.payload =[{
"series": ["A", "B", "C"],
"data": [
[{ "x": 1504029632890, "y": 5 },
{ "x": 1504029636001, "y": 4 },
{ "x": 1504029638656, "y": 2 }
],
[{ "x": 1504029633514, "y": 6 },
{ "x": 1504029636622, "y": 7 },
{ "x": 1504029639539, "y": 6 }
],
[{ "x": 1504029634400, "y": 7 },
{ "x": 1504029637959, "y": 7 },
{ "x": 1504029640317, "y": 7 }
]
],
"labels": [""]
}]
.
standard chart with data from above code
I know node-red dashboard chart is similar to chart.js. I can send ui_control message to adjust actual y-axe and add two more y-axis:
let msg2=
{
ui_control :{
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'minute',
unitStepSize: 1,
displayFormats: {
minute: 'HH:mm'
}
}
}],
yAxes: [{
id: "1",
scaleLabel: {
display: true,
labelString: 'pressure [bar]'
},
ticks: {
min: -10,
max: 10,
stepSize: 2
}
}, {
id: "2",
scaleLabel: {
display: true,
labelString: 'Temperature [°C]'
},
ticks: {
min: 0,
max: 20,
stepSize: 4
}
}, {
id: "3",
scaleLabel: {
display: true,
labelString: 'Flow [L/min]'
},
ticks: {
min: 0,
max: 20,
stepSize: 4
}
}]
} ,
legend: {
display: true,
position: 'top',
},
title: {
display: true,
text: 'Chart'
}
,
animation: {
duration: 0
}
}},
};
return msg2;
Result is:
Same data, ui_control message result
And now I want display for example:
msg.payload = 5;
msg.topic="C";
msg.yAxis="3";
return msg;
and instead get "C" on axe 3 (temperature), I get it on axe 1 (pressure), and Node-red sometimes freeze after send above message.
chart with one data point on 1 y axe
So now proper question: How Can I use more than one y axis? Can I done this with standard node-red dashboard chart? How data structure should look for static chart, and how for live chart? Maybe I should use node-red template node and write code in HTML based on chart.js? And one last question, how can I minimalize PC usage, because when I run 30 sensors, at 4Hz, I get 1200 point in just 10s?
I will be grateful for your help :D

If a radar chart values are full it occupies half the space (Chart.js)

I created a radar chart that has full values, but if its full, the area occupied is 50%, any way to fix that? (even if that is as designed).
https://codepen.io/asaadmahmood/pen/XWgrGWg
<canvas id="marksChart" width="600" height="400"></canvas>
var marksCanvas = document.getElementById("marksChart");
var marksData = {
labels: ["English", "Maths", "Physics", "Chemistry", "Biology", "History"],
datasets: [{
label: "Student A",
backgroundColor: "rgba(200,0,0,0.2)",
data: [100, 100, 100, 100, 100, 100]
}]
};
var radarChart = new Chart(marksCanvas, {
type: 'radar',
data: marksData
});
Figured it out, need to set:
scales: {
r: {
beginAtZero: true,
}
}

Highchart - Unable to parse my JSON string as a variable in the series but hardcoded way seems to work fine

I am trying to create a highchart based on dynamic data in my Javascript file. I have created a function called dynamicHighchart and it is parsing in JSON 'myJsonString'
The below works fine which is what I got from the console log:
series: [{ "name": "Oct 20", "type": "line", "data": [24025, 24200, 24075, 23925, 23950, 23850, 23650] }, { "name": "Nov 20", "type": "line", "data": [18875, 19125, 18125, 17650, 17500, 16375, 14725, 16625, null, 15550, 14875, 14900, 14925, 15450, 16125, 14500, 13375, 14150, 14150, 12900, 12600, 12950, 13200, 13125, 13175, 13000, 13100, 13100, 13150] }]
but doing this doesn't work - shows as an empty chart:
series: myJsonString
The way I got my stringify JSON is using the following line of code:
myJsonString = JSON.stringify(arr);
Am I parsing myJSON variable in correctly to the series?
My highchart function:
function dynamicHighchart(myJsonString) {
console.log(myJsonString);
var chart = new Highcharts.Chart({
chart: {
renderTo: 'chart1div',
zoomType: 'xy'
},
title: {
text: 'Chart Title'
},
xAxis: {
title: {
enabled: true,
text: 'X axis title'
},
},
yAxis: {
title: {
text: 'Y axis title'
}
},
series: myJsonString
//series: [{ "name": "Oct 20", "type": "line", "data": [24025, 24200, 24075, 23925, 23950, 23850, 23650] }, { "name": "Nov 20", "type": "line", "data": [18875, 19125, 18125, 17650, 17500, 16375, 14725, 16625, null, 15550, 14875, 14900, 14925, 15450, 16125, 14500, 13375, 14150, 14150, 12900, 12600, 12950, 13200, 13125, 13175, 13000, 13100, 13100, 13150] }]
});
}
You need to parse your data from string to an array:
Highcharts.chart('container', {
series: JSON.parse(myJsonString),
...
});
Live demo: http://jsfiddle.net/BlackLabel/c562p8mj/

How to Create synchronized High chart with different no of series per chart

I want to create a synchronized High chart with two charts and the 1st chart will have one series and 2nd chart will have 2 series.
this link contains the sync chart with two series each chart, but when I reduced data to my required condition crosshair did not work properly.
data for chart.
var activity = {
"xData": [1, 1056, 2161, 3215, 4267],
"datasets": [{
"name": "Chart 1 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 1 series 2",
"data": [23, 84, 22, 5, 75],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 2 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "%",
"type": "line",
"valueDecimals": 1
}]
You are going from 2 series on each chart to 2 series on the 1st chart and 1 series on the 2nd chart, so you will be getting an error while trying your updated activity data. You need to add a conditional check like this (comments in uppercase):
/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/
$(function () {
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove', function (e) {
var chart,
points,
i;
for (i = 0; i < Highcharts.charts.length; i++) {
chart = Highcharts.charts[i];
e = chart.pointer.normalize(e); // Find coordinates within the chart
// CHECK IF WE HAVE 2:
if ( chart.series.length === 2 ){
points = [chart.series[0].searchPoint(e, true), chart.series[1].searchPoint(e, true)]; // Get the hovered point
if (points[0] && points[1]) {
points[0].onMouseOver(); // Show the hover marker
points[1].onMouseOver(); // Show the hover marker
chart.tooltip.refresh(points); // Show the tooltip
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
}
// CHECK IF WE HAVE 1 CHART:
} else {
points = [chart.series[0].searchPoint(e, true)]; // Get the hovered poi
if (points[0]) {
points[0].onMouseOver(); // Show the hover marker
chart.tooltip.refresh(points); // Show the tooltip
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
}
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max);
}
}
});
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highslide-software/highcharts.com/blob/master/samples/data/activity.json
//$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function (activity) {
var activity = {
"xData": [1, 1056, 2161, 3215, 4267],
"datasets": [{
"name": "Chart 1 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 1 series 2",
"data": [23, 84, 22, 5, 75],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 2 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "%",
"type": "line",
"valueDecimals": 1
}]
},
lastChart;
$.each(activity.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, i) {
return [activity.xData[i], val];
});
if(i%2 == 0) { //first series of chart
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20,
// zoomType: 'x'
// pinchType: null // Disable zoom on touch devices
},
title: {
text: dataset.name.slice(0,7),
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
shared: true,
headerFormat: '',
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
visible:true
}
}]
});
} else { //second series of chart
lastChart = Highcharts.charts[Highcharts.charts.length-1];
lastChart.addSeries({
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
});
}
});
//});
});
Working JSFiddle: http://jsfiddle.net/kostasx/kfwtv1zj/

AmChart multiples date values

I'm trying to create a chart with multiples date values but it's not working. I thing that the logic is good and that amChart doesn't like this date format. Any ideas ?
The working exemple :
var chart = AmCharts.makeChart( "chartdiv", {
type: "xy",
dataProvider: [ {
"ax": 16.10, <--------
"ay": 2,
"bx": 16.11, <--------
"by": 2
}, {
"ax": 16.20, <--------
"ay": 3,
"bx": 16.21, <--------
"by": 3
}],
graphs: [ {
"xField": "ax",
"yField": "ay"
}, {
"xField": "bx",
"yField": "by"
} ],
} );
What I'm trying to get :
var chart = AmCharts.makeChart( "chartdiv", {
type: "xy",
dataProvider: [ {
"ax": "2017/04/27 09:16:10", <--------
"ay": 2,
"bx": "2017/04/27 09:16:11", <--------
"by": 2
}, {
"ax": "2017/04/27 09:16:20", <--------
"ay": 3,
"bx": "2017/04/27 09:16:21", <--------
"by": 3
}],
graphs: [ {
"xField": "ax",
"yField": "ay"
}, {
"xField": "bx",
"yField": "by"
} ],
} );
http://jsfiddle.net/Lktv4s4b/1/
For date-based data, you have to specify a dataDateFormat for your chart object so that AmCharts knows how to correctly parse your date. Since you're using an XY chart, you also have to tell AmCharts that you have a date-based value axis (XY charts only have value axes, unlike Serial charts) and you have to specify which one is date-based. Going by your data, your X axis is date-based, so you need to at least tell it that the bottom value axis' type is "date":
AmCharts.makeChart("chartdiv", {
type: "xy",
dataDateFormat: "YYYY/MM/DD JJ:NN:SS",
valueAxes: [{
position: "bottom",
type: "date"
}], //you can also specify the second value axis' properties if needed, but it will create a numeric y-axis for you by default if you don't
// ... rest of your properties omitted ...
});
Updated fiddle: http://jsfiddle.net/Lktv4s4b/2/

Categories