Highchart stacked area not functioning with missing datapoint - javascript

The issue is that the percentage area function does not seem to work when a datetime series is missing a datapoint for some t.
E.g. removing
{
x: new Date("2008-10-31T00:00:00.000Z"),
y: 0,
drilldown: 'my_drilldown'
}
from the series in http://jsfiddle.net/qtoas0jg/3/, giving http://jsfiddle.net/qtoas0jg/4/.
The expected/desired behaviour is that the area should fill for all times t. After going through the documentation I conclude that connectNulls:false, also using step:"left" I can achieve the desire behaviour for one series, the one holding values for all t, but then again not for the second series.
Any ideas?
EDIT:
I was not able to solve the issue using Highcharts functionality. Instead I (quite unrigiously) manipulated the series that I put in by adding value 0 for the missing t. If someone stumbles apon this issue, the following might be useful:
let asd = []
// Firstly finding which t:s that need to be added for respective series
let to_be_added = series.map(arg_a => {
return([arg_a.name,arg_a.data.reduce((acc_b,arg_b) => {
// Adding all available t:s
(asd.indexOf(arg_b.x.toString())>=0?0:asd.push(arg_b.x.toString()))
acc_b.push(arg_b.x.toString())
return acc_b
},[])])
}).map(arg_a => {
return [arg_a[0],asd.filter(arg_b => arg_a[1].indexOf(arg_b)<0)]
})
// Adding the new timestamps with y:0
to_be_added.map(arg_a => {
series.map((arg_b,ind) => {
if (arg_b.name == arg_a[0]) {
arg_a[1].reverse().map(arg_c => {
series[ind].data.unshift({x:new Date(arg_c),y:0})
})
}
})
})

This problem is caused by Highcharts bug: https://github.com/highcharts/highcharts/issues/5634
To workaround use timestamps instead of Date object:
data: [{
x: new Date("2008-10-31T00:00:00.000Z").getTime(),
...
}, ...]
Live demo: http://jsfiddle.net/BlackLabel/0wr3kvt1/

Related

Highcharts JS- add third variable to tooltip for two series

I've already figured out how to make a chart using highcharts where there are three variables- one on the X axis, one on the Y axis, and one on the tooltip. The way to do this is to add the following to the tooltip:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
const pointData = chartData.find(row => row.timestamp === this.point.x)
return pointData.somethingElse
}
}
See this fiddle for the full code:
https://jsfiddle.net/m9e6thwn/
I would simply like to do the same, but with two series instead of one. I can't get it to work. I tried this:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
const pointData = chartData1.find(row => row.timestamp === this.point.x)
return pointData.somethingElse
const pointData2 = chartData2.find(row => row.timestamp === this.point.x)
return pointData2.somethingElse
}
}
Here is the fiddle of the above: https://jsfiddle.net/hdeg9x02/ As you can see, the third variable only appears on one of the two series. What am I getting wrong?
There are some issues with the way you are using the formatter now. For one, you cannot have two returns in the same function without any if clauses. That will mean that only the first return will be used.
Anyway, here are some improvements I suggest you do for your code.
Add the extra information for each point to highcharts, that makes it a lot easier to access this information through highcharts. E.g. in a tooltip. You can set the data like this:
chartData1.map(function(row) {
return {
x: row.timestamp,
y: row.value,
somethingElse: row.somethingElse
}
})
If you do that, then returning the correct tooltip for each series is a simple matter of doing this:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
return this.point.somethingElse
}
}
Working JSFiddle example: https://jsfiddle.net/ewolden/dq7L64jg/6/
If you wanted more info in the tooltip you could then do:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
return this.point.somethingElse + ", time: " + str(this.x) + ", value: " + str(this.y)
}
}
Addtionally, you need to ensure that xAxis elements, i.e. your timestamps are sorted. This is a requirement for highcharts to function properly. As it is, your example is reporting
Highcharts error #15: www.highcharts.com/errors/15
in console, because chartData2 is in reverse order. It looks okay for this example, but more complicated examples can lead to the chart not looking as you expect it to.
For this example using reverse is easy enough: data: chartData2.reverse().map(function(row) {return {x: row.timestamp, y: row.value, somethingElse: row.somethingElse}})
Working JSFiddle example: https://jsfiddle.net/ewolden/dq7L64jg/7/

D3: Zoom with multiple line charts somehow combines their data arrays

I've got a chart with some random data. On button click I'd like to add another chart on top of the first one. That works fine. I've also included zoom and it works fine with only the first chart. Zooming with both charts somehow copies the data from the second chart to the first one.
Have a look at the example. You should be able to see the blue chart. Click the button to add the green one. Now try to zoom in. The blue one disappears. However it is not gone. It is simply hidden behind the green one. They are perfectly on top of each other although they should have different values.
https://codesandbox.io/s/31lz6zrln5
Any ideas?
Best regards,
Mirco
In the button callback you modify the data elements.
filtered = () => {
const values = [...data].map(d => {
d.value = rnd(25, 75);
return d;
});
this.chart.filtered(values);
};
You should return new objects based on the fields of the other objects
filtered = () => {
const values = [...data].map(d => {
return { timestamp: d.timestamp, value: rnd(25, 75) };
});
this.chart.filtered(values);
};
Also update the filtered path in the zoom callback
public zoom = () => {
const newXScale = event.transform.rescaleX(this.xScale);
const newYScale = event.transform.rescaleY(this.yScale);
this.xAxisGroup.call(this.xAxis.scale(newXScale));
this.yAxisGroup.call(this.yAxis.scale(newYScale));
this.xGridGroup.call(this.xGrid.scale(newXScale));
this.yGridGroup.call(this.yGrid.scale(newYScale));
this.line.x(d => newXScale(d.timestamp)).y(d => newYScale(d.value));
this.lineGroup.attr("d", this.line as any);
this.lineFiltered.attr("d", this.line as any); // removed the comment of this line
};

Plotly.js hover across multiple subplots

I have a plotly.js graph with multiple subplots that share an x-axis as in https://plot.ly/javascript/subplots/#stacked-subplots-with-a-shared-x-axis
I'm trying to hover across all of the subplots so that the values of all of the points with the same x value are displayed at once.
I've attempted to solve this by calling Plotly.Fx.hover on each subplot, but it only seems to take effect for the last subplot on which it is called.
http://codepen.io/john-soklaski/pen/adQwBa
The code I tried is:
Plotly.Fx.hover('myDiv', {xval: 2, curveNumber: 0}, "xy")
Plotly.Fx.hover('myDiv', {xval: 2, curveNumber: 1}, "xy2")
Ideally the API would be such that I could do this in a single call:
Plotly.Fx.hover('myDiv', [{xval: 2, curveNumber: 0, subplot: "xy"}, {xval: 2, curveNumber: 1, subplot: "xy2"}])
Any thoughts on how to get this to work?
I see this question is old, but this functionality has been added: https://github.com/plotly/plotly.js/pull/301
Plotly.plot('myDiv', data, layout);
graph = document.getElementById('myDiv');
graph.on('plotly_hover', function(eventdata) {
if (eventdata.xvals) {
Plotly.Fx.hover(graph, {
xval: eventdata.xvals[0]
}, ['xy', 'x2y2', 'x3y3', 'x4y4']);
}
});
For multiple subplots add the axis labels array also.
In this case
['xy', 'x2y2', 'x3y3', 'x4y4']
In this way you can get coupled hover events for subplots in a div
You'll have to pass the visible subplots as the third arg to Plotly.Fx.hover func.
This worked for me:
chartContainer.current.on('plotly_hover', function () {
var points = eventdata.points[0]
var pointNum = points.pointNumber
Plotly.Fx.hover(
chartContainer.current,
props.data.map((_, i) => ({
curveNumber: i,
pointNumber: pointNum
})),
Object.keys((chartContainer.current)._fullLayout._plots))
})
chartContainer.current is the div here.
Object.keys((chartContainer.current)._fullLayout._plots) will return the visible plots, for example: ['xy', 'xy2'...]

C3js customize tooltip of scatter chart

I created a scatter chartlike this in the JSfiddle (http://jsfiddle.net/q8h39/102/)
which is doing two dimension data analysis.
but I need to contain some extra information (e.g: custom names and a extra count value) in the chart** and give different color for each of the plots.
I tried to create an Array and use the tooltip library like this but i didn't reach the goal yet still.
var nameArr = ['anson','jason','samson','dickson']; // Names
tooltip: {
format: {
title: function (d) { return nameArr; },
}
}
Please see the JSfiddle code for further details, many thanks
The below is the current result and the exception exception after development
i have gone through the jsfiddle link and there were two issue with this:-
c3js library is old
c3js does not provide this functionality out of the box but you can achieve this using trick.
I have fixed both of above given issues and now it is working fine.
jsfiddle:-
http://jsfiddle.net/q8h39/109/
code for setting the tooltip:-
tooltip: {
format: {
title: function(x) {
var indOfVal = engagmentArr.indexOf(x);
return nameArr[indOfVal - 1]
},
name: function() {
return engagmentArr[0];
}
},
},

Highcharts displaying improperly labeled data points

I'm having an issue with highcharts displaying some of my datapoints with a duplicate label, then skipping subsequent labels, and I can't figure out how to fix it.
I gather from reading various posts that this is an issue with the PointInterval option; I'd like to set its value to 1 month, but since months a different lengths, this is not simple.
I am not sure of what a proper solution is though. Here is my code:
http://jsfiddle.net/KJ3tk/
The graph is displaying January and March twice, and skipping February.
The solution suggested in this thread ( http://highslide.com/forum/viewtopic.php?f=9&t=17269 ) seems to be what I need, but I can't figure out how to implement it in the javascript that I currently have. This is the code that they suggest will fix the problem:
var data = [3,2,5,3,5,6,2,3,1];
var month = 4; // the first month
data = $.map(data, function(value) {
return {
x: Date.UTC(2000, month++, 1),
y: value
};
});
I'd really appreciate any assistance! Thanks.
var mydata = [
7418,7386,7552,8903,8439,9356,9861,9411,10257,10169,9622,9940,
/*2009*/
10551,10326,12817,11739,11694,12209,12132,11842,11908,11909,11884,12450,
/*2010*/
15545,14495,16195,15064,13788,14452,14908,15858,16213,15994,15213,15651,
/*2011*/
17233,15515,19629,18960,19834,19997,19358,21042,20189,20660,20034,19815,
/*2012*/
22611,21435,23327,22876,22986,23692,21581,21832,22337
];
var month = 0; // the first month
mydata = $.map(mydata, function(value) {
return {
x: Date.UTC(2008, month++, 1),
y: value
}; });
Live Demo

Categories

Resources