2011-12-21 12 views
7

Biorąc linii X pikseli długo jak:Linear X Skala logarytmiczna

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

Jeśli 0 <= V <= max, w skali liniowej V pozycja byłaby X/max*V pikseli.

Jak mogę obliczyć położenie piksela dla skali logarytmicznej i począwszy od pozycji piksela, w jaki sposób mogę odzyskać wartość V?

  1. To nie jest praca domowa
  2. Chcę wiedzieć matematyki (nie „Użyj bla-plotlib” komentuje, proszę)
  3. lubię Pythona

skali logarytmicznej ma wpływu "powiększanie" lewej strony skali. Czy można zamiast tego zrobić to samo dla prawej strony?

[UPDATE]

Dzięki za lekcje z matematyki!

Skończyło się, że nie używam logarytmów. Po prostu użyłem średniej wartości (w zbiorze wartości) jako środka skali. Ta kontrola służy do wybierania percentyle granicy grupy dla zestawu wartości, które będą używane do rysowania choropleth chart.

Jeśli użytkownik zdecyduje się skalą symetrycznego (czerwony znak = średni, zielony znacznik = center, ciemność oznacza liczbę wystąpień wartości): enter image description here

asymetryczny skala sprawia drobnoziarniste korekty łatwiejsze: enter image description here

+0

rejestruje wszystkie wartości, a reszta jest taka sama. uważaj, że nie możesz mieć zera (log (0) jest neg .. inf) ani przekroczyć znaku – yosukesabai

+0

@yosukesabai: jakiejkolwiek podpowiedzi o tym, jak radzić sobie z bardzo niskimi wartościami 'max'? –

+2

To jest '(X/maks.) * V', a ładniejsze do odczytania jako' X * V/max' – wim

Odpowiedz

13

Więc masz trochę arbitralne wartości V, i wiesz, że 0 = V < < = Vmax. Chcesz obliczyć współrzędną x piksela, nazwij go X, gdzie twój "ekran" ma współrzędne x od 0 do Xmax. Jak można powiedzieć, aby to zrobić „normalna” sposób, można by zrobić

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

Lubię myśleć o tym jak ja pierwszy normalizację wartości leżą między 0 a 1 obliczając V/Vmax, a następnie Powtarzam tę wartość przez maksimum, aby uzyskać wartość od 0 do tego maksimum.

Aby zrobić to samo logarytycznie potrzebny jest inny niższy limit dla wartości V. Jeśli V jest kiedykolwiek < = 0, otrzymasz ValueError. Powiedzmy: 0 < Vmin < = V < = Vmax. Następnie musisz dowiedzieć się, z jakiego logarytmu należy korzystać, ponieważ istnieje nieskończenie wiele z nich.Trzy są powszechnie spotykane, te z podstawy 2, E i 10, co skutkuje w osi x, które wyglądają tak:

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

Więc w zasadzie, jeśli uda nam się na wykładniki z wyrażeń w lewo, . możemy zastosować tę samą zasadę jak wyżej, aby uzyskać wartość pomiędzy 0 a Xmax, a to jest oczywiście gdzie log przychodzi w Zakładając użyć bazy b, można korzystać z tych wyrażeń do konwersji iz powrotem:

from math import log 
logmax = log(Vmax/Vmin, b) 
X = Xmax * log(V/Vmin, b)/logmax 
V = Vmin * b ** (logmax * X/Xmax) 

To prawie taki sam sposób myślenia, z tym wyjątkiem, że najpierw musisz upewnić się, że log(somevalue, b) da ci nie-negatywny e wartość. Robisz to dzieląc przez Vmin wewnątrz funkcji log. Teraz możesz podzielić maksymalną wartość wyrażenia, którą można uzyskać, co oczywiście wynosi log(Vmax/Vmin, b), a otrzymasz wartość między 0 a 1, tak jak poprzednio.

W inny sposób musimy najpierw normalizować (X/Xmax), a następnie ponownie zwiększyć skalę (* logmax) do maksymalnego oczekiwanego przez funkcję odwrotną. Odwrotność polega na podniesieniu wartości b do pewnej wartości. Teraz, jeśli X ma wartość 0, b ** (logmax * X/Xmax) będzie równe 1, więc aby uzyskać prawidłowy dolny limit, pomnóżmy wartość przez Vmin. Lub mówiąc inaczej, ponieważ pierwszą rzeczą, którą zrobiliśmy w drugą stronę, było podzielenie przez Vmin, musimy pomnożyć z Vmin jako ostatnią rzeczą, jaką robimy teraz.

Aby "powiększyć" "prawą stronę" równania, wszystko, co musisz zrobić, to przełączać równania, więc potęguje się przechodzenie od V do X i logarytm idzie w drugą stronę. Zasadniczo tak jest. Bo masz też coś zrobić z faktem, że X może być 0:

logmax = log(Xmax + 1, b) 
X = b ** (logmax * (V - Vmin)/(Vmax - Vmin)) - 1 
V = (Vmax - Vmin) * log(X + 1, b)/logmax + Vmin 
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 jest podstawa logarytmu jest)

Oczywiście należy upewnić się, że v> = 1 (V = 1 będzie odpowiadać pos = 0, V = 0..1 odpowiada -inf..0, a dla V < 0 nie zdefiniowano logarytmu).

2

Można to łatwo rozszerzyć na inne funkcje. Moja miara przestrzeni jest podana w znakach zamiast w pikselach (to dlatego max == chars (lub piksele)).
Tylko dla wartości dodatnich.

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

nadzieję, że powyższe nie jest uważany bla-plotlib. Ale do cholery! to jest tak ! :-)