I currently have a HighCharts graph, with the x-axis range 300 to 1 (1 being the highest rank, and 300 to be the lowest).
The problem is that if the data points range from 200 to 1, the change from 10 to 1 does not look significant.
Is there anyway to modify a HighCharts graph to stretch out the changes that are closer to the highest value (1) so that the jump in values are more significant?
Related
I have a set graph that ranges from 300 - 850 on the y-axis, and the user can update the chart and select a 3, 6, or 12 month range on the x-axis, where the far right value should be the most recent month in the data set. But Chart.js appends the data that is out of my label range: ] where
labels: ["Apr'17", "May'17", "Jun'17"]
data: [{"x": "Jan'17", "y": 565},{"x": "Mar'17","y": 765},{"x": "Jun'17","y": 665}]
I only want the Jun'17 data point shown here, but Jan'17 and Mar'17 data points are appended. I can add a max, min limit on the x-scale, but is that the only way to accomplish this? There seems like there should be a cleaner solution.
It works with the 6 month range as I would expect with the same data, but the previous three months added to the labels array:
I have the following chart here:
what I'd like to do is shift the X axis so that the path only reaches the half of the width and the rest is blank (planning to put some plotlines there of some future events) - any ideas how to do it? Cheers :)
To achieve this you simply need to give your x axis a max property.
max: Number
The maximum value of the axis. If null, the max value is automatically calculated. If the endOnTick option is true, the max value might be rounded up.
– xAxis.max - Highstock API
They give a demo of this here: http://jsfiddle.net/gh/get/jquery/2/highcharts/highcharts/tree/master/samples/stock/xaxis/min-max/
In your case, if you're wanting your current data to end half way along the x axis, you need to set the max to the difference between where the data starts and where the data currently ends on top of the point the data currently ends.
As you haven't specified any code yourself, I'm going to use dummy values. If your x axis data starts at 5 and ends at 8, the difference between 5 and 8 is 3, so you need to add that to 8 to offset the chart:
xAxis: {
max: 11 // (8 - 5 + 8)
}
I am trying to draw a chart using d3-js. I want X axis values to be [0.25yrs; 0.50yrs; 1yr; 2yrs; 5 yrs; 10yrs; 15yrs; 20yrs; 30 yrs; 50 yrs]. This can be done using d3's tickValues() & tickFormat() functions. But I need to maintain certain distance between 0.25, 0.50 & 1 year ticks, because most values belong to these years & more distance between them will reduce overlapping of drawn circles.
The tick position I need is something like :
You can see the distance between .01 and .02 in above image. How can we do that?
You will need to implement a custom scale that maps your input range to this non-uniform output range. Then you can give this scale to your axis and it will draw the ticks accordingly.
You could have a look at the scales that D3 provides if anything is close enough to what you want (a log scale maybe?), but if you can't find anything you have no choice but to implement your own.
I'm generating bar graphs. The range of data generating said graphs is very wide, which means some areas of the graph are always low, and some areas go off the chart.
What's the math to "normalize" this towards a certain number (e.g. 200), so large values are shrunk the larger they are, and smaller values are increased?
If you are talking about actually changing the data for display purposes, then there are a few basic approaches to bring values closer to a target value. The simplest is to just do a weighted average with that value: A' = (1-α)*A + α*B where alpha is a weight between 0 and 1, A is a number on your graph, and B is the target value.
For instance, if you were trying to 'normalize' to 200 and your numbers were 100 120 200 220 400 then plugging in each for A, 200 for B, and .5 for alpha, you would get 150 160 200 210 300
You can choose a different alpha to adjust how much you want to stretch the data towards the target value. Higher numbers like .9 will stretch the data more and lower numbers like .1 will stretch the data less.
I dont know if you are willing to read a little but I found the the scaling tutorial for d3.js framework (http://d3js.org/) is a very solid introduction to the scaling part of visualisation:
http://alignedleft.com/tutorials/d3/scales/
For a zero-based graph : compute the max of your value, then display for each bar :
barHeight[i] = (maxBarHeight*value[i])/maxVal;
If you want your graph to be based on the minimum value and not zero, you might still want the
graph to have a non-zero height for the bar near the min value. So compute the minimum value, and display :
barHeight[i] = minBarHeight +
(maxBarHeight - minBarHeight ) * (value[i] - minVal) / ( maxVal - minVal );
( Rq : if minVal is Zero or 'near' zero, set minVal = minBarHeigth = 0 and you have the first case )
We're attempting to display two series of data on the same chart. The first series (ie: number of quotations) can only contain positive integers (and 0). The second series (ie: sales value) can contain both positive and negative float values (in case you're wondering, the negative values result from the issuing of credit notes).
As indicated on the attached image, the problem we're having is that when the second series contains negative values, the 0-point "base line" of the two series of data is no longer shared.
We've tried setting the "min" options of the Y axes to 0, but then we lose out the insight on negative values.
We've also tried setting the min of the first series to be equal to the minimum extreme of the second series, but unfortunately this doesn't scale the columns very nicely (since the values of each Y axis are on completely different scales, ie: 10s vs 1000s).
How can we configure the chart so that the 0-point "base line" is shared? In other words, how would we make the blue columns start at the same base line as the green 0 point?
Update
Linger's answer is a step in the right direction. Setting the min and tickinterval for both axes does the trick. However the values need to be determined dynamically based on variable data, which is where I am now stuck.
Any tips on how these min and tickinterval values can be determined before I generate the chart?
I've done some thinking about it in the mean time. The values associated with the left axis (blue / quotations) are always positive and start from zero. Thus it is the right axis (green / sales) that dictates the number of ticks to show below the zero point. Now since highcharts automatically determines the best scale for both blue and green, all I need to do is find a way to set the left axis' minimum value like so (excuse the pseudo-code):
var factor = right_axis.min / right_axis.tickinterval;
left_axis.min = factor * left.tickinterval;
Note: I have seen the reference API has a setExtremes() method under Axis, but this would require me to first initialise the chart, and then go back and update its left axis. I am hoping to do this before drawing the chart. Perhaps I'm overlooking something obvious?
Thanks.
You can control what you are asking for with a combination of tickInterval and min on the yaxis as demonstrated in this jsfiddle mock up.
EDIT
In your code while reading in the XML you will have to keep track of what the lowest value is and also the highest value on the sales side. Then decide how you want to display those values if they meet a certain value. After that use if statements to set the values. Here is a couple of examples.
Low less than -50 and greater -90
With High less than 400
Primary Axis: min: -2, tickInterval: 1,
Secondary Axis: min: -100, tickInterval: 50
Example
Low less than -50 and greater -90
With High greater than 400
Primary Axis: min: -1, tickInterval: 1,
Secondary Axis: min: min: -100, tickInterval: 100,
Example
To figure out what the min on the Primary Axis should be you simply divide the min on the Secondary Axis by its tickInterval. Then the tickInterval for the Primary Axis would always be 1.
You can also calculate second axis tick positions based on the max series value related to this axis and the first axis ticks positions to get the same amount of ticks and 0 line shared.
Using axis.update() method update tick positions in the second axis using property tickPositions.
Example with a load event. Notice, that when you add points dynamically you have to make those calculations and update tick positions each time your first axis ticks will change:
chart: {
type: 'column',
events: {
load: function() {
var chart = this,
yAxis = this.yAxis,
max = yAxis[1].dataMax,
positiveTicksAmount = 0,
negativeTicksAmount = 0,
tickPositions = [],
tickInterval,
min,
i;
yAxis[0].tickPositions.forEach(function(tick) {
if (tick > 0) {
positiveTicksAmount++;
} else if (tick < 0) {
negativeTicksAmount++;
}
});
tickInterval = max / positiveTicksAmount;
for (i = negativeTicksAmount; i > 0; i--) {
tickPositions.push(-tickInterval * i);
}
for (i = 0; i <= positiveTicksAmount; i++) {
tickPositions.push(
tickInterval * i
);
}
yAxis[1].update({
tickPositions: tickPositions
});
}
}
},
Jsfiddle examples:
https://jsfiddle.net/wchmiel/84q0sxrt/
http://jsfiddle.net/wchmiel/nuj7fagh/
Api reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#update
https://api.highcharts.com/highcharts/yAxis.tickPositions