给定一行X
像素长度:
0-------|---V---|-------|-------|-------max
如果0 <= V <= max
,则线性比例V
位置将为X/max*V
像素。
如何计算对数刻度的像素位置,从像素位置开始如何取回V的值?
对数刻度具有“缩放”刻度左侧的效果。是否有可能为右侧做同样的事情?
[UPDATE]
感谢数学课程!
我最终没有使用对数。我只是使用平均值(在一组值中)作为比例的中心。此控件用于为将用于绘制choropleth chart的一组值选择组边界百分位数。
如果用户选择对称刻度(红色标记=平均值,绿色标记=中心,黑暗表示值的出现次数):
非对称比例使细粒度调整更容易:
答案 0 :(得分:14)
所以你有一些任意值V
,而且你知道0&lt; = V
&lt; = Vmax
。您想要计算像素的x坐标,将其称为X
,其中“屏幕”的x坐标从0到Xmax
。正如你所说,要做到“正常”的方式,你要做
X = Xmax * V / Vmax
V = Vmax * X / Xmax
我喜欢把它想象成我首先通过计算V / Vmax
将值归一化到介于0和1之间,然后我将此值乘以最大值以获得介于0和最大值之间的值。
要进行相同的logaritmically,您需要V
值的不同下限。如果V始终<= 0,则得到ValueError
。所以我们说0&lt; Vmin
&lt; = V
&lt; = Vmax
。然后你需要找出使用什么对数,因为它们中有很多。通常遇到三个,那些有基数2,e和10,这导致x轴看起来像这样:
------|------|------|------|---- ------|------|------|------|----
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
所以原则上,如果我们可以从左边的表达式得到指数,我们就可以使用与上面相同的原理得到一个介于0和Xmax
之间的值,这当然是log来的地方在。假设您使用基础b
,您可以使用这些表达式来回转换:
from math import log
logmax = log(Vmax / Vmin, b)
X = Xmax * log(V / Vmin, b) / logmax
V = Vmin * b ** (logmax * X / Xmax)
这几乎是相同的思维方式,除了你需要首先确保log(somevalue, b)
会给你一个非负值。您可以在Vmin
函数中除以log
来执行此操作。现在你可以除以表达式可以产生的最大值,当然是log(Vmax / Vmin, b)
,你将获得一个介于0和1之间的值,与之前相同。
我们需要首先规范化(X / Xmax
)的另一种方式,然后再次(* logmax
)向上扩展到反函数所期望的最大值。顺便说一句,反之是将b
提升到某个值。现在,如果X
为0,则b ** (logmax * X / Xmax)
将等于1,因此要获得正确的下限,我们乘以Vmin
。换句话说,因为我们以另一种方式做的第一件事是除以Vmin
,我们需要乘以Vmin
作为我们现在做的最后一件事。
要“缩放”等式的“右侧”,您需要做的就是切换方程式,以便取幂从V
到X
并取对数走向另一个方向。原则上,就是这样。因为你还必须对X
可以为0的事实做一些事情:
logmax = log(Xmax + 1, b)
X = b ** (logmax * (V - Vmin) / (Vmax - Vmin)) - 1
V = (Vmax - Vmin) * log(X + 1, b) / logmax + Vmin
答案 1 :(得分:2)
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是对数的基础)
显然你必须确保V&gt; = 1(V = 1将对应于pos = 0,V = 0..1对应于-inf..0,而对于V&lt; 0对数未定义)。< / p>
答案 2 :(得分:2)
这可以很容易地扩展到其他功能。我的空间度量是以字符而不是像素给出的(这就是为什么max == chars(或像素)) 仅适用于正值。
import math
def scale(myval, mode='lin'):
steps = 7
chars = max = 10 * steps
if mode=='log':
val = 10 * math.log10(myval)
else:
val = myval
coord = []
count = 0
not_yet = True
for i in range(steps):
for j in range(10):
count += 1
if val <= count and not_yet:
coord.append('V')
not_yet = False
pos = count
elif j==9:
coord.append('|')
else:
coord.append('*')
graph = ''.join(coord)
text = 'graph %s\n\n%s\nvalue = %5.1f rel.pos. = %5.2f\n'
print text % (mode, graph, myval, chars * pos/max)
scale(50, 'lin')
scale(50, 'log')
希望以上不被认为是FOO-plotlib。该死的!这是啊! : - )