dygraphs Reverse y-axis with dynamic maximum (lower value) - javascript

What I would like to have: a dygraphs plot with reverse y-axis as shown in the documentation example:
https://github.com/danvk/dygraphs/blob/master/tests/reverse-y-axis.html except I would like the y-max value (now at the bottom) to be dynamic so that its value is equal to the maximum data value in the zoom.
I have tried to set value range as valueRange: [ , 0] in place of valueRange: [ 3000, 0] (which works fine for non-reversed y-axis).
But in the reverse y-axis example yields this:
The original with fixed reverse y-axis valueRange: [ 3000, 0] was this:
I could try adding a zoom listener and then after each zoom set the valueRange: to [ max_value, 0 ]
where max_value is for that specific zoom. But I'd very much like a simpler/cleaner solution if one exists.
Any suggestions appreciated! Thanks!

To decide whether to flip the y-axis, dygraphs looks at whether the min y-value is greater than the max y-value. If you don't specify one, it can't do that, so that's not going to work.
Probably the easiest solution is to flip the y-axis after the data loads:
g = new Dygraph(div, data, options);
g.ready(() => {
const [minY, maxY] = g.yAxisRange();
// Change either of these to a hard-coded value as you wish:
g.updateOptions({valueRange: [maxY, minY]});
});
Full example here.

Related

Manually set y-axis min and max value and zoom-in behaviour in Highcharts

I want to know the rounded min and max value that Highcharts will set on each axis before those are rendered out given minValue, maxValue and tickAmount.
My current solution is to manually calculate tickPositions so that it will show exactly what I set. So in a way, I know the values of them beforehand. The problem with this is when I zoom in, no new ticks for the zoomed-in interface are added. The reason for this is because the tickPositions attribute has blocked it from adding new ticks.
I have two questions:
- Is there any method provided by Highcharts does the min and max value? So that I can get those beforehand.
- Or is there an algorithm that Highcharts follow to calculate those value? I will implement that algorithm again to get those values?
- Or is there a way to manually implement the adding-new-ticks behaviour by myself? This is for using tickPositions.
You can use tickPositioner function to define your own logic to draw ticks:
yAxis: {
tickPositioner: function(min, max) {
if (this.chart.resetZoomButton) { // zoomed chart
return [1, 7]
}
return [1, 3, 5, 7]
}
}
Live demo: http://jsfiddle.net/BlackLabel/s8Ldhfcy/
API Reference: https://api.highcharts.com/highcharts/yAxis.tickPositioner

Highcharts Y-Axis Limits

I am having problems controlling the Y-Axis range of a highcharts graph. It seems like highcharts likes nice round numbers. When my data passes or is close to certain thresholds, the Y-Axis range can expand a lot which effectively compresses all the plot points downward.
Here is a jsfiddle that illustrates the problem I am having:
https://jsfiddle.net/shannonwrege/z8h5eork
The relevant code for this post is this:
chart.yAxis[0].setExtremes(0, max, true, false);
Keep in mind that I don't know what the data will look like in advance, so I must dynamically modify the Y-Axis range. Right now I am using the setExtremes because of other suggestions I've read on stackoverflow.
The maximum y-value of the data in the first two charts is 99. You'll notice that the y-axis is set at 150 in the first chart where the range is automatically calculated and 100 in the second chart where I specifically set the extreme values. The look of the 2nd chart is what I want. So it seems like setExtremes(0,99,true,false) should do the trick, but it actually doesn't.
In the 3rd chart I changed the data so that the maximum y-value of the data is 101, and I called setExtremes(0,101,true,false). You'll note that the y-axis is now back to 150.
Ideally I want the scale of the graph to be capped on the maximum value to limit the about of extra white space. I want to see all of the data, but I don't necessarily care about the y-axis displaying a maximum band that is greater than the max data value. In this case, I would be happy with the y-axis displaying 100 on the axis and some points over but still visible.
Does anyone know how to make this work?
I ended up using the endOnTick parameter to solve this problem. Adding the following line to the yAxis configuration parameters did exactly what I wanted:
endOnTick: false,
Here's the updated Fiddle showing the results.
https://jsfiddle.net/shannonwrege/z8h5eork/3/
All of the charts look pretty good in my opinion (even the one where the yAxis range was auto calculated).
You will need to read the data and then round up to set the idealMax
var chart,
idealMax = 0; // init the max value
// Read the data to find the highest value
for (i=0;i < (options.series[0].data).length; i++ ){
if (options.series[0].data[i][1] > idealMax) {
idealMax = options.series[0].data[i][1];
}
}
// Round the max to the nearest 10
idealMax = Math.round(idealMax / 10) * 10;
options.yAxis.tickPixelInterval = idealMax/10;
Highcharts.chart('container1', options);
chart = $('#container1').highcharts();
chart.yAxis[0].setExtremes(0, idealMax, true, false);
Updated Fiddle

Stockcharts - Adding an offset to avoid drawing points at the edge

Highcharts and stockcharts, they both provide the options to add some padding at the x axis in order to avoid drawing some values on the edge of the plot area (left or right).
According to the doc this is archived by employing the minPadding and maxPadding members of the xAxis property of the configuration object used for constructing the chart... but in practice this is not working for stockcharts. So i wonder how i can achieve this... i leave you with the examples...
var examples
Working example for highcharts
Not Working example for stockcharts
P.D: Using property min for setting the lowest x value also isn't working.
The maxPadding is applied when you not call the setExtremes() method. In the Highstock, we call the setExtremes to set the range on the navigator, as a result padding is ignored.
To achieve your goal, you can define the tickLength parameter and set x param per labels.
yAxis: {
tickWidth: 1,
tickLength: 50,
labels:{
x: 50
}
},
Example:
http://jsfiddle.net/b6a42kz0/
OP Note: See the comments for updated answer.

Does d3.js offer a method to extend my dataset to the origin of my graph?

Take this scenario from a graph I'm working on at the moment:
The problem I'm having is in the bottom left. My dataset's first coordinate is defined at approximately (60,5), yet the domain I'm looking to cover extends right down to 0. Is there any way I can get d3 to extrapolate this data to my origin? I've browsed the API but nothing clearly stands out.
I'm well aware I could just .push a new object with coordinates (0,0) onto my dataset array, but I would prefer not to as I may need to do manipulation with my data later, making this an undesirable option.
Since you have not provided a fiddle i chose to put up a small fiddle to explain this:
My Data set is like this:
data = [{
xval: 10,
yval: 100
}, {
xval: 40,
yval: 90
}, {
xval: 50,
yval: 12
}, {
xval: 90,
yval: 70
}]
You can see the values of x and y value varies from 0 to 100.
So you will define the range like:
x.domain([0, 100]);//this will show x axis start from 0
y.domain([0,100]);//this will show y axis start from 0
example here:
as per your requirement you want the y axis to start from 10 so you do
x.domain([0, 100]);//this will show x axis start from 0
y.domain([10,100]);//this will show y axis start from 10
example here
Hope this solves your problem. ..:)
You can also adjust your data domain to the maximum and the minimum using the extent function that d3 provides.
var x_domain = d3.extent(data,function(d){return d.xval});
var y_domain = d3.extent(data,function(d){return d.yval});
x.domain(x_domain);
y.domain(y_domain);
That way the graph will always be adjusted to the data domain in both coordinates whatever data comes.
Watch this working.
Well, I found an answer to my own question here.
d3 will never extend a line beyond the final data point.
The solution is the following:
If your really must have the line start and end at the very end of your range, then you have two options:
Create a custom interpolation function; or,
Add an "end-value" data point when you pass your data array to d3.svg.line.
For me, it looks like I'm going to have to include a "start value" datapoint. Disappointing.

How do I avoid duplicate labels in C3JS

I have a graph in C3JS and i was trying to avoid duplicate labels. When I have a large range of data it does not duplicate the labels but with a small range of data it does.
How do I have it so that it will only display the numbers 19-23% in this case.
Solution 1:- Use axis.tick.limit config set to lesser value like 4 or 5, so that less number of tick values are shown.
Solution 2:- Set axis.tick.format config to a function, which returns percentages a rational number like 20.0%, 20.5%, 21.0%, 21.5%, etc.
Second solution is better.
From the additional y axis labels, it looks like you have already overridden the format function, Just make sure it returns percentages with decimals.
axis: {
y2: {
tick: {
count:3, // Limit number of axis ticks (solution 1)
format: function(d){//logic to return formatted percentages with decimal digit}
}
}
}

Categories

Resources