【问题标题】:Linear X Logarithmic scale线性 X 对数刻度
【发布时间】:2012-01-25 01:15:09
【问题描述】:

给定一条X 像素长的行:

0-------|---V---|-------|-------|-------max

如果0 <= V <= max,在线性比例V 位置将是X/max*V 像素。

如何计算对数刻度的像素位置,从像素位置开始如何取回 V 的值?

  1. 这不是家庭作业
  2. 我想知道数学(请不要“使用 FOO-plotlib”cmets)
  3. 我喜欢 Python

对数刻度具有“缩放”刻度左侧的效果。是否可以对右侧做同样的事情?

[更新]

感谢数学课!

我最终没有使用对数。我只是使用平均值(在一组值中)作为刻度的中心。此控件用于为一组值选择组边界百分位数,这些值将用于绘制choropleth chart

如果用户选择了一个对称的刻度(红色标记=平均,绿色标记=中心,黑暗代表一个值的出现次数):

不对称比例使细粒度调整更容易:

【问题讨论】:

  • 记录所有值,其余相同。小心你不能有零(log(0)是负数。inf)也不能越过符号
  • @yosukesabai:关于如何处理非常低的 max 值的任何提示?
  • 那是(X/max)*V,更容易读成X * V/max
  • 如何定义右侧缩放?
  • @hamstergene:在图表中使刻度右侧的值更加稀疏。

标签: python math


【解决方案1】:

所以你有一些任意值V,你知道 0 V Vmax。你想计算一个像素的 x 坐标,称之为X,你的“屏幕”的 x 坐标从 0 到Xmax。正如您所说,要以“正常”方式执行此操作,您会这样做

X = Xmax * V / Vmax
V = Vmax * X / Xmax

我喜欢这样想,我首先通过计算 V / Vmax 将值标准化为介于 0 和 1 之间,然后将此值乘以最大值以获得介于 0 和最大值之间的值。

要以对数方式执行相同操作,您需要为 V 值设置不同的下限。如果 V 永远 ValueError。所以假设 0 Vmin V 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 的用武之地。假设您使用 base 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) 会给你一个非负值。您可以通过在log 函数中除以Vmin 来实现。现在你可以除以表达式可以产生的最大值,当然是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

【讨论】:

    【解决方案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。但是该死!就是这样! :-)

    【讨论】:

      【解决方案3】:
                 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 >= 1(V=1 将对应于 pos=0,V=0..1 对应于 -inf..0,对于 V

      【讨论】:

        猜你喜欢
        • 2013-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-28
        • 2011-03-28
        • 2016-11-05
        相关资源
        最近更新 更多