2011-12-21 25 views
7

Dada una línea X píxeles de largo como:Linear X escala logarítmica

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

Si 0 <= V <= max, en escala lineal V posición sería X/max*V píxeles.

¿Cómo puedo calcular la posición del píxel para una escala logarítmica y, a partir de la posición del píxel, cómo puedo recuperar el valor de V?

  1. No es tarea
  2. Quiero saber las matemáticas (no "utilizar FOO-plotlib" comentarios, por favor)
  3. me gustan Python

Una escala logarítmica tiene el efecto de "acercar" el lado izquierdo de la escala. ¿Es posible hacer lo mismo por el lado derecho?

[ACTUALIZACIÓN]

Gracias por las lecciones de matemáticas!

Terminé sin usar logaritmos. Simplemente utilicé el valor promedio (en un conjunto de valores) como el centro de la escala. Este control se usa para seleccionar percentiles de límites de grupo para un conjunto de valores que se usarán para dibujar un choropleth chart.

Si el usuario elige una escala simétrica (marca roja = promedio, marca verde = centro, la oscuridad representa el número de ocurrencias de un valor): enter image description here

Una escala asimétrica hace ajustes de grano fino más fácil: enter image description here

+0

tomar el registro de todos los valores y el resto es el mismo. tenga cuidado de que no pueda tener cero (log (0) es neg. inf) ni cruce el signo – yosukesabai

+0

@yosukesabai: ¿alguna pista sobre cómo lidiar con valores muy bajos de 'max'? –

+2

Eso es '(X/max) * V', y mejor para leer como' X * V/max' – wim

Respuesta

13

por lo que tiene algún valor arbitrario V, y ustedes saben que 0 = < V < = Vmax. Si desea calcular la coordenada x de un píxel, llámelo X, donde su "pantalla" tiene coordenadas x de 0 a Xmax. Como usted dice, hacer esto de la manera "normal", que haría

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

me gusta pensar en él como si estuviera primera normalizar el valor de estar entre 0 y 1 mediante el cálculo de V/Vmax, y luego Multiplico este valor por el máximo para obtener un valor entre 0 y ese máximo.

Para hacer lo mismo logarítmicamente necesita un límite inferior diferente para el valor V. Si V alguna vez es < = 0, obtiene ValueError. Digamos que 0 < Vmin < = V < = Vmax. Luego debe averiguar qué logaritmo usar, ya que hay infinitos de ellos.Tres se encuentran comúnmente, los que tienen base 2, E y 10, lo que resulta en el eje x que se parecen a esto:

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

Por lo tanto, en principio, si podemos llegar a los exponentes de las expresiones de la izquierda, . podemos utilizar el mismo principio que el anterior para obtener un valor entre 0 y Xmax, y esto es por supuesto donde log viene en Suponiendo que utilice la base b, puede utilizar estas expresiones para convertir de ida y vuelta:

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

Es casi la misma forma de pensar, excepto que primero debe asegurarse de que log(somevalue, b) le otorgue un valor no negativo valor de e Para ello, divida por Vmin dentro de la función log. Ahora puedes dividir por el valor máximo que puede arrojar la expresión, que es, por supuesto, log(Vmax/Vmin, b), y obtendrás un valor entre 0 y 1, igual que antes.

De la otra manera primero tenemos que normalizar (X/Xmax), luego aumentar (* logmax) al máximo esperado por la función inversa. Lo contrario es aumentar b a algún valor, por cierto. Ahora bien, si X es 0, b ** (logmax * X/Xmax) será igual a 1, entonces, para obtener el límite inferior correcto, multiplicamos por Vmin. O para decirlo de otra manera, ya que lo primero que hicimos al otro lado fue dividir por Vmin, necesitamos multiplicarnos por Vmin como lo último que hacemos ahora.

Para "acercar" el "lado derecho" de la ecuación, todo lo que tiene que hacer es cambiar las ecuaciones, por lo que expones el valor de V a X y lleva el logaritmo al revés. En principio, eso es. Debido a que también tiene que hacer algo con el hecho de que X puede ser 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 es la base del logaritmo)

Obviamente debe asegurarse de que V> = 1 (V = 1 corresponderá a pos = 0, V = 0..1 corresponde a -inf..0, y para V < 0 logaritmo no está definido).

2

Esto se puede ampliar fácilmente para otras funciones. Mi medida de espacio se da en caracteres en lugar de píxeles (por eso max == caracteres (o píxeles)).
Solo para valores positivos.

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

esperan que el FOO-plotlib anterior no se considera. Pero maldita sea! Es tan ! :-)

Cuestiones relacionadas