Given a line X
pixels long like:
0-------|---V---|-------|-------|-------max
If 0 <= V <= max
, in linear scale V
position would be X/max*V
pixels.
How can I calculate the pixel position for a logarithmic scale, and starting from the pixel position how can I get back the value of V?
A logarithmic scale has the effect of "zooming" the left side of the scale. Is it possible to do the same thing for the right side instead?
[UPDATE]
Thanks for the math lessons!
I ended up not using logarithms. I've simply used the average value (in a set of values) as the center of the scale. This control is used to select group boundary percentiles for a set of values that will be used to draw a choropleth chart.
If the user chooses a symmetric scale (red mark=average, green mark=center, darkness represents the number of occurrences of a value):
An asymmetric scale makes fine-grained adjustments easier:
A logarithmic price scale uses the percentage of change to plot data points, so, the scale prices are not positioned equidistantly. A linear price scale uses an equal value between price scales providing an equal distance between values.
The X axis usually plots the independent variable – the variable you control. If you chose X values that are constant ratios, rather than constant differences, the graph will be easier to view on a logarithmic axis.
There are two main reasons to use logarithmic scales in charts and graphs. The first is to respond to skewness towards large values; i.e., cases in which one or a few points are much larger than the bulk of the data. The second is to show percent change or multiplicative factors.
A log-linear model is a mathematical model that takes the form of a function whose logarithm equals a linear combination of the parameters of the model, which makes it possible to apply (possibly multivariate) linear regression.
So you've got some arbitrary value V
, and you know that 0 <= V
<= Vmax
. You want to calculate the x-coordinate of a pixel, call it X
, where your "screen" has x-coordinates from 0 to Xmax
. As you say, to do this the "normal" way, you'd do
X = Xmax * V / Vmax
V = Vmax * X / Xmax
I like to think of it like I'm first normalizing the value to lie between 0 and 1 by calculating V / Vmax
, and then I multiply this value by the maximum to get a value between 0 and that maximum.
To do the same logaritmically you need a different lower limit for the V
value. If V is ever <= 0, you get a ValueError
. So let's say 0 < Vmin
<= V
<= Vmax
. Then you need to find out what logarithm to use, as there are infinitely many of them. Three are commonly encountered, those with base 2, e and 10, which results in x-axis that look like this:
------|------|------|------|---- ------|------|------|------|----
2^-1 2^0 2^1 2^2 == 0.5 1 2 4
------|------|------|------|---- ------|------|------|------|----
e^-1 e^0 e^1 e^2 == 0.4 1 2.7 7.4
------|------|------|------|---- ------|------|------|------|----
10^-1 10^0 10^1 10^2 == 0.1 1 10 100
So in principle, if we can get at the exponents from the expressions to the left, we can use the same principle as above to get a value between 0 and Xmax
, and this is of course where log comes in. Assuming you use base b
, you can use these expressions to convert back and forth:
from math import log
logmax = log(Vmax / Vmin, b)
X = Xmax * log(V / Vmin, b) / logmax
V = Vmin * b ** (logmax * X / Xmax)
It's almost the same way of thinking, except you need to first make sure that log(somevalue, b)
will give you a non-negative value. You do this by dividing by Vmin
inside the log
function. Now you may divide by the maximum value the expression can yield, which is of course log(Vmax / Vmin, b)
, and you will get a value between 0 and 1, same as before.
The other way we need to first normalize (X / Xmax
), then scale up again (* logmax
) to the maximum expected by the inverse funciton. The inverse is to raise b
to some value, by the way. Now if X
is 0, b ** (logmax * X / Xmax)
will equal 1, so to get the correct lower limit we multiply by Vmin
. Or to put it another way, since the first thing we did going the other way was to divide by Vmin
, we need to multiply with Vmin
as the last thing we do now.
To "zoom" the "right side" of the equation, all you need to do is switch the equations, so you exponentiate going from V
to X
and take the logarithm going the other way. In principle, that is. Because you've also got to do something with the fact that X
can be 0:
logmax = log(Xmax + 1, b)
X = b ** (logmax * (V - Vmin) / (Vmax - Vmin)) - 1
V = (Vmax - Vmin) * log(X + 1, b) / logmax + Vmin
Linear Logarithmic
Forward pos = V * X/max pos = log(V) * X/log(max)
Reverse V = pos * max/X V = B^( pos * log(max)/X )
(B is logarithm's base)
Obviously you must ensure that V >= 1 (V=1 will correspond to pos=0, V=0..1 corresponds to -inf..0, and for V<0 logarithm is not defined).
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