I need to make a chart with an optimized y axis maximum value.
The current method I have of making charts simply uses the maximum value of all the graphs, then divides it by ten, and uses that as grid lines. I didn't write it.
Update Note: These graphs have been changed. As soon as I fixed the code, my dynamic graphs started working, making this question nonsensical (because the examples no longer had any errors in them). I've updated these with static images, but some of the answers refrence different values. Keep that in mind. There were between 12003 and 14003 inbound calls so far in February. Informative, but ugly.
I'd like to avoid charts that look like a monkey came up with the y-axis numbers.
Using the Google charts API helps a little bit, but it's still not quite what I want. The numbers are clean, but the top of the y value is always the same as the maximum value on the chart. This chart scales from 0 to 1357. I need to have calculated the proper value of 1400, problematically.
I'm throwing in rbobby's defanition of a 'nice' number here because it explains it so well.
I found the way to get the results that I want using a modified version of Mark Ransom's idea.
Fist, Mark Ransom's code determines the optimum spacing between ticks, when given the number of ticks. Sometimes this number ends up being more than twice what the highest value on the chart is, depending on how many grid lines you want.
What I'm doing is I'm running Mark's code with 5, 6, 7, 8, 9, and 10 grid lines (ticks) to find which of those is the lowest. With a value of 23, the height of the chart goes to 25, with a grid line at 5, 10, 15, 20, and 25. With a value of 26, the chart's height is 30, with grid lines at 5, 10, 15, 20, 25, and 30. It has the same spacing between grid lines, but there are more of them.
So here's the steps to just-about copy what Excel does to make charts all fancy.
PHP:
function roundUp($maxValue){ $optiMax = $maxValue * 2; for ($i = 5; $i <= 10; $i++){ $tmpMaxValue = bestTick($maxValue,$i); if (($optiMax > $tmpMaxValue) and ($tmpMaxValue > ($maxValue + $maxValue * 0.05))){ $optiMax = $tmpMaxValue; $optiTicks = $i; } } return $optiMax; } function bestTick($maxValue, $mostTicks){ $minimum = $maxValue / $mostTicks; $magnitude = pow(10,floor(log($minimum) / log(10))); $residual = $minimum / $magnitude; if ($residual > 5){ $tick = 10 * $magnitude; } elseif ($residual > 2) { $tick = 5 * $magnitude; } elseif ($residual > 1){ $tick = 2 * $magnitude; } else { $tick = $magnitude; } return ($tick * $mostTicks); }
Python:
import math def BestTick(largest, mostticks): minimum = largest / mostticks magnitude = 10 ** math.floor(math.log(minimum) / math.log(10)) residual = minimum / magnitude if residual > 5: tick = 10 * magnitude elif residual > 2: tick = 5 * magnitude elif residual > 1: tick = 2 * magnitude else: tick = magnitude return tick value = int(input("")) optMax = value * 2 for i in range(5,11): maxValue = BestTick(value,i) * i print maxValue if (optMax > maxValue) and (maxValue > value + (value*.05)): optMax = maxValue optTicks = i print "\nTest Value: " + str(value + (value * .05)) + "\n\nChart Height: " + str(optMax) + " Ticks: " + str(optTicks)
In math, a scale in graphs can be defined as the system of marks at fixed intervals, which define the relation between the units being used and their representation on the graph. Here, for instance, the scale of the graph is 1 interval being equal to 10 units.
This is from a previous similar question:
Algorithm for "nice" grid line intervals on a graph
I've done this with kind of a brute force method. First, figure out the maximum number of tick marks you can fit into the space. Divide the total range of values by the number of ticks; this is the minimum spacing of the tick. Now calculate the floor of the logarithm base 10 to get the magnitude of the tick, and divide by this value. You should end up with something in the range of 1 to 10. Simply choose the round number greater than or equal to the value and multiply it by the logarithm calculated earlier. This is your final tick spacing.
Example in Python:
import math def BestTick(largest, mostticks): minimum = largest / mostticks magnitude = 10 ** math.floor(math.log(minimum) / math.log(10)) residual = minimum / magnitude if residual > 5: tick = 10 * magnitude elif residual > 2: tick = 5 * magnitude elif residual > 1: tick = 2 * magnitude else: tick = magnitude return tick
You could round up to two significant figures. The following pseudocode should work:
// maxValue is the largest value in your chart magnitude = floor(log10(maxValue)) base = 10^(magnitude - 1) chartHeight = ceiling(maxValue / base) * base
For example, if maxValue
is 1357, then magnitude is 3 and base is 100. Dividing by 100, rounding up, and multiplying by 100 has the result of rounding up to the next multiple of 100, i.e. rounding up to two significant figures. In this case, the result if 1400 (1357 ⇒ 13.57 ⇒ 14 ⇒ 1400).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With