matrices graficos graficas graficar ejes dispersion diagrama coordenadas python numpy matplotlib graphing

python - graficos - Escala de registro de Matplotlib Marque el formato del número de etiqueta



matplotlib python 3 (4)

Con matplotlib cuando se especifica una escala logarítmica para un eje, el método predeterminado para etiquetar ese eje es con números que son 10 a una potencia, por ejemplo. 10 ^ 6. ¿Hay alguna manera fácil de cambiar todas estas etiquetas para que sean su representación numérica completa? p.ej. 1, 10, 100, etc.

Tenga en cuenta que no sé cuál será el rango de potencias y quiero admitir un rango arbitrario (negativos incluidos).


Claro, solo cambia el formateador.

Por ejemplo, si tenemos esta trama:

import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.axis([1, 10000, 1, 100000]) ax.loglog() plt.show()

Puede establecer las etiquetas de tic tac de forma manual, pero luego las ubicaciones de tic y las etiquetas se corregirán cuando haga zoom / pan / etc. Por lo tanto, es mejor cambiar el formateador:

from matplotlib.ticker import ScalarFormatter for axis in [ax.xaxis, ax.yaxis]: axis.set_major_formatter(ScalarFormatter())


Descubrí que utilizar ScalarFormatter es excelente si todos los valores de tilde son mayores o iguales que 1. Sin embargo, si tiene un tic en un número <1 , ScalarFormatter imprime la etiqueta de tilde como 0 .

He usado esta función lambda con FuncFormatter para establecer los números >= 1 en su valor entero, y los números <1 en su valor decimal, con el número mínimo de decimales requerido (es decir 0.1, 0.01, 0.001 , etc.). Supone que solo está configurando ticks en los valores base10 .

import matplotlib.ticker as ticker import numpy as np ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,pos: (''{{:.{:1d}f}}''.format(int(np.maximum(-np.log10(y),0)))).format(y)))

Para mayor claridad, aquí está la función lambda escrita de una manera más detallada, pero también más comprensible:

def myLogFormat(y,pos): # Find the number of decimal places required decimalplaces = int(np.maximum(-np.log10(y),0)) # =0 for numbers >=1 # Insert that number into a format string formatstring = ''{{:.{:1d}f}}''.format(decimalplaces) # Return the formatted tick label return formatstring.format(y) ax.yaxis.set_major_formatter(ticker.FuncFormatter(myLogFormat))


Encontré Tom''s respuestas de Joe''s y Tom''s muy útiles, pero hay muchos detalles útiles en los comentarios sobre esas respuestas. Aquí hay un resumen de los dos escenarios:

Rangos superiores a 1

Aquí está el código de ejemplo como Joe, pero con un rango más alto:

import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.axis([1, 10000, 1, 1000000]) ax.loglog() plt.show()

Eso muestra una trama como esta, usando notación científica:

Como en la respuesta de Joe, uso un ScalarFormatter , pero también lo llamo set_scientific(False) . Eso es necesario cuando la báscula sube a 1000000 o más.

import matplotlib.pyplot as plt from matplotlib.ticker import ScalarFormatter fig, ax = plt.subplots() ax.axis([1, 10000, 1, 1000000]) ax.loglog() for axis in [ax.xaxis, ax.yaxis]: formatter = ScalarFormatter() formatter.set_scientific(False) axis.set_major_formatter(formatter) plt.show()

Rangos por debajo de 1

Como en la respuesta de Tom, esto es lo que sucede cuando el rango va por debajo de 1:

import matplotlib.pyplot as plt from matplotlib.ticker import ScalarFormatter fig, ax = plt.subplots() ax.axis([0.01, 10000, 1, 1000000]) ax.loglog() for axis in [ax.xaxis, ax.yaxis]: formatter = ScalarFormatter() formatter.set_scientific(False) axis.set_major_formatter(formatter) plt.show()

Eso muestra los primeros dos tics en el eje x como ceros.

El cambio a FuncFormatter encarga de eso. Una vez más, tuve problemas con los números 1000000 o superior, pero al agregar una precisión a la cadena de formato lo resolvió.

import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter fig, ax = plt.subplots() ax.axis([0.01, 10000, 1, 1000000]) ax.loglog() for axis in [ax.xaxis, ax.yaxis]: formatter = FuncFormatter(lambda y, _: ''{:.16g}''.format(y)) axis.set_major_formatter(formatter) plt.show()


con respecto a estas preguntas

¿Qué pasa si quiero cambiar los números a, 1, 5, 10, 20?
- aloha 10 de julio de 15 a 13:26

Me gustaría agregar ticks entre medio, como 50,200, etc., ¿Cómo puedo hacer eso? Intenté, set_xticks [50.0,200.0] ¡pero eso no parece funcionar! - ThePredator 3 de agosto de 15 a 12:54

Pero con ax.axis ([1, 100, 1, 100]), ScalarFormatter da 1.0, 10.0, ... que no es lo que deseo. Quiero que den enteros ... - CPBL 7 de diciembre de 15 a 20:22

puedes resolver esos problemas de esta manera con el formateador MINOR:

ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f")) ax.set_yticks([0.00000025, 0.00000015, 0.00000035])

en mi aplicación estoy usando este esquema de formato, que creo que resuelve la mayoría de los problemas relacionados con el formato escalar de registro; lo mismo podría hacerse para el formato de datos> 1.0 o eje x:

plt.ylabel(''LOGARITHMIC PRICE SCALE'') plt.yscale(''log'') ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%.8f")) ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f")) ##################################################### #force ''autoscale'' ##################################################### yd = [] #matrix of y values from all lines on plot for n in range(len(plt.gca().get_lines())): line = plt.gca().get_lines()[n] yd.append((line.get_ydata()).tolist()) yd = [item for sublist in yd for item in sublist] ymin, ymax = np.min(yd), np.max(yd) ax.set_ylim([0.9*ymin, 1.1*ymax]) ##################################################### z = [] for i in [0.0000001, 0.00000015, 0.00000025, 0.00000035, 0.000001, 0.0000015, 0.0000025, 0.0000035, 0.00001, 0.000015, 0.000025, 0.000035, 0.0001, 0.00015, 0.00025, 0.00035, 0.001, 0.0015, 0.0025, 0.0035, 0.01, 0.015, 0.025, 0.035, 0.1, 0.15, 0.25, 0.35]: if ymin<i<ymax: z.append(i) ax.set_yticks(z)

para comentarios sobre "force autoscale" ver: Python matplotlib logarítmico autoscale

cuyos rendimientos:

luego para crear una máquina de uso general:

# user controls ##################################################### sub_ticks = [10,11,12,14,16,18,22,25,35,45] # fill these midpoints sub_range = [-8,8] # from 100000000 to 0.000000001 format = "%.8f" # standard float string formatting # set scalar and string format floats ##################################################### ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter(format)) ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter(format)) #force ''autoscale'' ##################################################### yd = [] #matrix of y values from all lines on plot for n in range(len(plt.gca().get_lines())): line = plt.gca().get_lines()[n] yd.append((line.get_ydata()).tolist()) yd = [item for sublist in yd for item in sublist] ymin, ymax = np.min(yd), np.max(yd) ax.set_ylim([0.9*ymin, 1.1*ymax]) # add sub minor ticks ##################################################### set_sub_formatter=[] for i in sub_ticks: for j in range(sub_range[0],sub_range[1]): set_sub_formatter.append(i*10**j) k = [] for l in set_sub_formatter: if ymin<l<ymax: k.append(l) ax.set_yticks(k) #####################################################

rendimientos: