Линейный Х Логарифмическая шкала - PullRequest
8 голосов
/ 21 декабря 2011

Для данной строки X пикселей, таких как:

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

Если 0 <= V <= max, то в линейном масштабе V позиция будет X/max*V пикселей.

Как рассчитать положение пикселя для логарифмической шкалы и, исходя из положения пикселя, как вернуть значение V?

  1. Это не домашняя работа
  2. Я хочу знать математику (пожалуйста, не используйте комментарии "use FOO-plotlib")
  3. Мне нравится Python

Логарифмическая шкала имеет эффект "увеличения" левой частимасштаб.Можно ли сделать то же самое для правой стороны?

[ОБНОВЛЕНИЕ]

Спасибо за уроки математики!

В итоге я не использовал логарифмы.Я просто использовал среднее значение (в наборе значений) в качестве центра шкалы.Этот элемент управления используется для выбора процентилей границы группы для набора значений, которые будут использоваться для рисования хороплетной диаграммы .

Если пользователь выбирает симметричную шкалу (красная метка = средняя, ​​зеленая)знак = центр, темнота представляет количество вхождений значения): enter image description here

Асимметричная шкала облегчает детальную настройку: enter image description here

Ответы [ 3 ]

14 голосов
/ 21 декабря 2011

Итак, у вас есть произвольное значение V, и вы знаете, что 0 <= <code>V <= <code>Vmax.Вы хотите вычислить x-координату пикселя, назовите его X, где ваш "экран" имеет x-координаты от 0 до Xmax.Как вы говорите, чтобы сделать это "нормальным" способом, вы должны сделать

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

Мне нравится думать об этом, как будто я сначала нормализую значение, лежащее между 0 и 1, вычисляя V / Vmax, а затем я умножаю это значение на максимум, чтобы получить значение от 0 до этого максимума.

Чтобы сделать то же самое логарифмически, вам нужен другой нижний предел для значения V.Если V когда-либо <= 0, вы получите <code>ValueError.Итак, скажем, 0 <<code>Vmin <= <code>V <= <code>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, и это, конечно, то, где входит журнал. Предполагая, что вы используете 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) даст вам неотрицательное значение.Вы делаете это путем деления на Vmin внутри функции log.Теперь вы можете разделить максимальное значение, которое может дать выражение, которое, конечно, равно log(Vmax / Vmin, b), и вы получите значение в диапазоне от 0 до 1, как и раньше.

Другим способом, который нам нужно сначала нормализовать(X / Xmax), затем снова увеличьте масштаб (* logmax) до максимума, ожидаемого обратной функцией.Кстати, обратное - повысить b до некоторого значения.Теперь, если X равно 0, b ** (logmax * X / Xmax) будет равно 1, поэтому для получения правильного нижнего предела мы умножим на Vmin.Или, другими словами, поскольку первое, что мы сделали, - это деление на Vmin, нам нужно умножить на Vmin как последнее, что мы сейчас делаем.

To "zoom«Правая сторона» уравнения, все, что вам нужно сделать, это переключить уравнения, чтобы вы возвели в степень, переходя от 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 голосов
/ 21 декабря 2011

Это может быть легко расширено для других функций.Мера моего пространства дана в символах вместо пикселей (поэтому max == символов (или пикселей)).
Только для положительных значений.

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')

enter image description here

Надеюсь, что выше не считается FOO-plotlib.Но черт побери!это так !: -)

2 голосов
/ 21 декабря 2011
           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 <0 логарифм не определен). </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...