Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm for determining Y-axis labels and positions?

Given an array of y-values, like [-3400, -1000, 500, 1200, 3790], how do I determine "good" Y-axis labels and positions them on a grid?

           ^
---(6,000)-|---
           |
---(4,000)-|---
           |
---(2,000)-|---
           |
<------(0)-+---------------------------------------->
           |
--(-2,000)-|---
           |
--(-4,000)-|---
           V
like image 245
Julian Avatar asked Sep 06 '25 03:09

Julian


1 Answers

You could do it along the following lines:

  1. Figure out the number of labels you want to have (n). The result may not have exactly this many labels, but it will be close. I'm going to have n = 6.
  2. Decide, what numbers do you consider “pretty”. Do you only want to see steps like 1, 2, 5, 10, 20, 50, … (in this case, pretty numbers are 1, 2 and 5) or are steps like 1, 2, 4, 5, 6, 8, 10, … good too? I'm going to consider only 1, 2 and 5.
  3. Find out the minimum (min) and maximum (max) of the sequence, the rest of the numbers don't matter. (min = -3400, max = 3790)
  4. Calculate the ideal, but ugly step between labels as uglyStep = (max - min) / (n - 2). We subtract two for the label at the bottom and at the top. (uglyStep = 1797)
  5. Calculate the order of magnitude of the uglyStep as magnitude = 10 ^ floor(log10(uglyStep)). (magnitude = 1000)
  6. Pick the best pretty step, by multiplying magnitude by all pretty numbers and by ten. Then choose the number with lowest difference between it and uglyStep. This will be prettyStep. (prettyStep = 2000)
  7. Compute the positions of the bottom and top label as bottom = floor(min / prettyStep) * prettyStep and top = ceil(max / prettyStep) * prettyStep. Note that / denotes normal mathematical division, not C-like integer division. (bottom = -4000, top = 4000)
  8. Every number between bottom and top that is divisible by prettyStep is going to have a label. (-4000, -2000, 0, 2000, 4000)

This might need some modifications if you don't want min and max to be very close to bottom and top.

Also, it sometimes behaves somewhat oddly, e.g. for min = 0 and max = 3002, it chooses 0, 500, 1000, 1500, 2000, 2500, 3000, 3500, but for max = 3005, it uses 0, 1000, 2000, 3000, 4000.

like image 184
svick Avatar answered Sep 08 '25 19:09

svick