Chart.js: passing objects instead of int values as data - javascript

Is it possible to pass an array of objects instead of an array of integers? The following code works but results in a flat zero line:
var ctx = document.getElementById("a").getContext("2d");
var data = {
labels: ["Fri", "Sat", "Sun"],
datasets: [{
label: "Chart B",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(150,150,150,1)",
pointColor: "rgba(150,150,150,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [{
y: 48,
name: "Value one",
date: "2015-04-30"
}, {
y: 40,
name: "Value two",
date: "2016-05-30"
}, {
y: 19,
name: "Value three",
date: "2016-06-30"
} ]
}]
};
var Chart = new Chart(ctx).Line(data);

In short, I think your example should work. The key is to use y for the y value in the chart, and to add your arbitrary property to the object, as well.
It looks like this is what you're doing, but you've reported it's not working... It works for me, though! ?
Longer answer
According to the docs for Line, data can be a Number[]:
data: [20, 10]
...but it can also be a Point[]:
data: [{
x: 10,
y: 20
}, {
x: 15,
y: 10
}]
This was intended to be used for sparsely-populated data sets. Through experimentation, I've found you can omit the x property and simply specify the y property. The x value will be inferred, as usual.
You can also add in any other arbitrary properties that can be accessed from your label callback. So, you might end up with something like this:
data: [{
y: 20,
myProperty: "Something"
}, {
y: 10,
myProperty: "Something Else"
}]

I can confirm that answer #rinogo gave works on latests version. You can add custom properties to dataset and use 'em in tooltip or elsewhere afterwards.
First add data to dataset. On my case I only have one set, so I'm just pushing points.
chartData.datasets[0].data.push({
y: groupedBooking.distinctCount,
distinctUsers: distinctUsers
});
... and finally override callback with chartOptions:
options: {
tooltips: {
callbacks: {
label(tooltipItem, data) {
console.log(data);
return data.datasets[0].data[tooltipItem.index].distinctUsers;
}
}
}
}
If you would happen to have multiple datasets you get datasetIndex from tooltipItem as well... so to confirm, X can be omitted from datapoint and customer properties are preserved within object.

In the data structure doc (version 3.5.1 at the time of writing this), it is documented objects can be used as data and parsing option is also available to pick the keys.
Example from the doc:
data: {
datasets: [{
data: [{id: 'Sales', nested: {value: 1500}}, {id: 'Purchases', nested: {value: 500}}]
}]
},
options: {
parsing: {
xAxisKey: 'id',
yAxisKey: 'nested.value'
}
}

Related

how to update plotly.js chart with new data from website?

I am trying to update the chart with plotly.js with data from a server. My function should plot updated data in the charts every time new data is sent.
I have two different graphs in my chart. Both with the same X value but different values for the Y axis. I can create the expected graphs in the chart with the first values. But when new values are sent, the restyle function did not update the values.
I don't know how to parse the data to the restyle function. Or, do I need to use a different function?
var source = new EventSource("http://old.iolab.sk/evaluation/sse/sse.php");
source.onmessage = function(event) {
count++;
if(count == 1){ // only on first data from server
var layout = {title: "Website graph"};
var trace1 = {
x: [event.data.match(/\d+/g)[0]],
y: [(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])], // y1 from server
name: "hehe",
type: 'scatter'
};
var trace2 = {
x: [event.data.match(/\d+/g)[0]],
y: [(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])], // y2 from server
name: "hehe",
type: 'scatter'
};
Plotly.newPlot("websiteGraph", [trace1, trace2], layout);
return;
}
if(!isClicked){ // keeps updating the chart with data from the server until the button is clicked
trace1 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])]]},
trace2 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])]]};
Plotly.restyle("websiteGraph", trace1+trace2);
}
return;
}
This is the data from the server, one ID is for one update:
id: 0
data: {
data: "x": "0",
data: "y1": "0.05",
data: "y2": "1.03"
data: }
id: 1
data: {
data: "x": "1",
data: "y1": "0.077452406437284",
data: "y2": "1.0998476951564"
data: }
id: 2
data: {
data: "x": "2",
data: "y1": "0.1048994967025",
data: "y2": "1.0893908270191"
data: }
id: 3
data: {
data: "x": "3",
data: "y1": "0.13233595624294",
data: "y2": "1.0086295347546"
data: }
To answer your question, try using Plotly.react or Plotly.newPlot for new data.
Plotly.restyle seems to be wrong (layout changes only?), as well as some argument passed into the functions.
The comments and examples below are from the Plotly docs at https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrestyle.
To see the code in action, check out this fiddle: https://jsfiddle.net/a0cj6bnm/
In restyle, arrays are assumed to be used in conjunction with the trace indices provided. Therefore, to apply an array as a value, you need to wrap it in an additional array. For example:
var graphDiv = document.getElementById(graphDiv);
var update = {
opacity: 0.5,
marker: {
size: [40, 60, 80, 100],
color: ['rgb(93, 164, 214)', 'rgb(255, 144, 14)', 'rgb(44, 160, 101)', 'rgb(255, 65, 54)']
}
}
Plotly.restyle(graphDiv, update, 0);
Note: To me, it seems that restyle is for layout changes only. Not sure though. Instead of 0, restyle can get an array of values but this had no effect on my tests.
newPlot draws a new plot in an element, overwriting any existing plot. To update an existing plot in a , it is much more efficient to use Plotly.react than overwrite it.
The function seems to expect an array and a layout hash as an argument.
var graphDiv = document.getElementById(graphDiv);
var layout = {
title: "Website graph",
xaxis: {
title: 'Year',
showgrid: false,
zeroline: false
},
yaxis: {
title: 'Percent',
showline: false
}
};
var trace1 = {
x: [1],
y: [1], // y1 from server
name: "hehe1",
type: 'scatter'
};
var trace2 = {
x: [2],
y: [2],
name: "hehe2",
type: 'scatter'
};
Plotly.newPlot(graphDiv, [trace1, trace2], layout);
Plotly.react has the same signature as Plotly.newPlot above, and can be used in its place to create a plot, but when called again on the same will update it far more efficiently than Plotly.newPlot, which would destroy and recreate the plot. Plotly.react is as fast as Plotly.restyle/Plotly.relayout documented below.
var graphDiv = document.getElementById(graphDiv);
var trace1 = {
x: [1,2,3,4,5],
y: [1,3,5,7], // y1 from server
name: "hehe1",
type: 'scatter'
};
var trace2 = {
x: [2,3,4,5,7,8],
y: [2,2,2,2,3,4],
name: "hehe2",
type: 'scatter'
};
Plotly.react(graphDiv, [trace1, trace2], layout);

Plotly.js define shape of data

I'm pulling data from an API that comes back in the following format:
[{
"metadata": {"colName": "nameOfCol"},
"value": valueForCol // string or number or whatever
},
...]
But according to Plotly's website, they want two simple arrays of labels and columns:
var data = [{
values: [19, 26, 55],
labels: ['Residential', 'Non-Residential', 'Utility'],
type: 'pie'
}];
or:
var data = [{
x: ['giraffes', 'orangutans', 'monkeys'],
y: [20, 14, 23],
type: 'bar'
}];
Now there's quite a big dataset coming back, so I'd prefer to not have to loop through the whole set and extract the labels and values from everything. Is there a nice way to tell Plotly to loop through my data and find the labels and values?
I don't know what this would look like, maybe something like:
var data = [{
source: myData,
labels: "metadata.colName",
values: "value",
type: "pie"
}]
Short answer: no, there is no feature in Plotly.js for this, you'll unfortunately have to loop through and extract.

Non-static values for chart using CanvasJS?

I'm trying to figure out how to make a dynamic bar chart using CanvasJs.
The basic set up for the chart is as follows:
var chart = new CanvasJS.Chart("chartContainer", {
theme: "theme2",//theme1
title:{
text: "Basic Column Chart - CanvasJS"
},
animationEnabled: false, // change to true
data: [
{
// Change type to "bar", "area", "spline", "pie",etc.
type: "column",
dataPoints: [
{ label: "apple", y: 10 },
{ label: "orange", y: 15 },
{ label: "banana", y: 25 },
{ label: "mango", y: 30 },
{ label: "grape", y: 28 }
]
}
]
});
chart.render();
}
My goal is to use a simple variable to update the dataPoints instead of static numbers such as 10,15, 25.
User's will input numbers and the chart should update based on their input.
Is this possible to do? Setting "Y" to a variable breaks the chart thus far. I'm unsure how to make this work.
I've also tried setting var input = $('input').html
and setting y as input but it does not work.
Thanks!
If anyone else is trying to figure this out here is how this is handled:
Use variable to assign data points in creating CanvasJS graph?.
This also works with Charts.JS.

put different names to each bar in Highcharts

How I can rename each bar, I want to have different names. always it appears "bar1", "bar2", etc. this is the name of the series. but I want it to appear in place of those texts, others I want to customize. this is what I do. put different names, if there are 9 bars I want to put different names to the bars, bar1, bar2, bar3, Bar4, Bar5, Bar6, Bar7, Bar8, Bar9. I do not want to repeat
in my example.
series: [{
name: 'bar1',
data: [1000, 950, 920, 0, 850],
color: "#FF0000"
}, {
name: 'bar2',
data: [800, 770, 750, 0, 730],
color: "#000000"
}, {
name: 'bar3',
data: [600, 540, 535, 500, 30],
color: "#00FF00"
},
{
name: 'bar4',
data: [28, 28, 28, 28, 28],
color: "#00FF00"
}]
http://jsfiddle.net/05L1n3wb/
This is done by changing name: 'bar1' to something you want. If you still need series.name to be 'bar1' then you should really think harder about your data model. If you want to change the text displayed based on the contents of series.name you can do that with the label formatter or dataLabel formatter.
As you can read in previous answer, you can use dataLabels formatter for changing string you are displaying for your columns: http://api.highcharts.com/highcharts#plotOptions.bar.dataLabels.formatter
You can add custom parameter to your points, like name:
series: [{
name: 'bar1',
data: [{
y: 1000,
name: 'bar1'
}, {
y: 950,
name: 'bar5'
}, {
y: 920,
name: 'bar9'
}, {
y: 0,
name: 'bar13'
}, {
y: 850,
name: 'bar17'
}],
color: "#FF0000"
}]
and inside your dataLabels formatter you can display this parameter:
formatter: function() {
var string = this.point.name + ' ';
if (this.y <= 30) {
string += this.y;
}
return string;
}
example:
http://jsfiddle.net/05L1n3wb/2/

Highcharts - Update a series point [x,y] values?

I'm trying to update a point[x,y] in the chart.
What's the problem?
Ok, I chart and its chart series are like this:
series: [
{
enableMouseTracking: false,
name: 'Line1',
type: 'line',
color: '#5d5d5d',
yAxis: 1,
data: [[12000, 55.068493], [15064, 42.842]],
marker: {
symbol: 'circle'
}
},
{
enableMouseTracking: false,
name: 'Line2',
type: 'line',
color: '#5d5d5d',
yAxis: 1,
marker: {
symbol: 'circle'
},
data: [[12000, 57.671527], [16000, 42.620069]]
},{
name: 'TOM',
//type: 'line',
color: '#ff4100',
yAxis: 1,
marker: {
symbol: 'url(icons/tom.png)'
},
data: [
{
id:'tom_point',
color: '#00FF00',
y: fi_variable,
x: tom_variable
}
]
}
Now the thing is that, I'm checking if fi_variable or tom_variable has changed and if its true, update these two variables, and finally update the chart.
I have tried already, some methods like chart.series[0].data[0].update(y = 10); and its working for some points with fixed x,y values, but no luck for the rest of the points.
For Instance I use chart.series[0].data[1].update(y = 10); will work ok,
but this chart.series[0].data[3].update(y = 10); will not work.
1- Is there any way to replace the data[0] from the above code line with an id of a point in our case tom_point ?
Also I've tried this chart.series[0].setData([[tom_variable,fi_variable, 'tom_point']]);
and again it wont working when the point is with an id or without fixed values.
But If I try chart.series[0]data[0].setData([[tom_variable,fi_variable]]); it works but again not on 3rd element (in our case - as shown above) of the series.
I can get the values for this point with the following,
var tomPoint = chart.get('tom_point').y;
but I can't set any x,y values back to chart and update it (the chart).
I have also tried to check if the variables have changed and to redraw the chart with chart.redraw but nothing.
Any Ideas how can I get this to work?
Am I losing something?
Thank you in Advance for your time.
First of all you try to update point (data[3]) which doens't exist in serie. Secondly in case when you update you need to use
chart.series[0].data[1].update(10); or chart.series[0].data[1].update({y:10}); but not yoru figure
if you want to change the x value also then use
chart.series[0].data[0].update({
x: 10,
y: 100
})
this will update both x and y values like in this example http://jsfiddle.net/DCA8W/
Hope this is what you are looking for.
Ok, the solution finally was simple.
I've managed to update the point:
The third element in the series with the name TOM corresponds to
chart.series[2].
{ // chart.series[2]
name: 'TOM',
//type: 'line',
color: '#ff4100',
yAxis: 1,
marker: {
symbol: 'url(icons/tom.png)'
},
data: [
{
id:'tom_point',
color: '#00FF00',
y: fi_variable,
x: tom_variable
}
]
}
So in order to update [x,y] values of this point, you have to do it like that:
// TOM Point
`chart.series[2].data[0].update({x:var_x, y:var_y});`

Categories