Imposta l'intervallo della barra dei colori in matplotlib


156

Ho il codice seguente:

import matplotlib.pyplot as plt

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

plt.clf()
plt.pcolor(X, Y, v, cmap=cm)
plt.loglog()
plt.xlabel('X Axis')
plt.ylabel('Y Axis')

plt.colorbar()
plt.show()

Quindi questo produce un grafico dei valori 'v' sugli assi X vs Y, usando la mappa colori specificata. Gli assi X e Y sono perfetti, ma la mappa dei colori si estende tra il minimo e il massimo di V. Vorrei forzare la mappa dei colori tra 0 e 1.

Ho pensato di usare:

plt.axis(...)

Per impostare gli intervalli degli assi, ma questo richiede solo argomenti per il minimo e il massimo di X e Y, non della mappa colori.

Modificare:

Per chiarezza, supponiamo di avere un grafico i cui valori sono compresi (0 ... 0,3) e un altro grafico i cui valori (0,2 ... 0,8).

In entrambi i grafici, voglio che l'intervallo della barra dei colori sia (0 ... 1). In entrambi i grafici, voglio che questa gamma di colori sia identica usando l'intera gamma del cdict sopra (quindi 0,25 in entrambi i grafici saranno dello stesso colore). Nel primo grafico, tutti i colori compresi tra 0,3 e 1,0 non compariranno nel grafico, ma saranno nella chiave colourbar a lato. Nell'altro, tutti i colori compresi tra 0 e 0,2 e tra 0,8 e 1 non compariranno nel grafico, ma nel colore della barra laterale.

Risposte:


177

Utilizzo vmine vmaxforza l'intervallo per i colori. Ecco un esempio:

inserisci qui la descrizione dell'immagine

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )

def do_plot(n, f, title):
    #plt.clf()
    plt.subplot(1, 3, n)
    plt.pcolor(X, Y, f(data), cmap=cm, vmin=-4, vmax=4)
    plt.title(title)
    plt.colorbar()

plt.figure()
do_plot(1, lambda x:x, "all")
do_plot(2, lambda x:np.clip(x, -4, 0), "<0")
do_plot(3, lambda x:np.clip(x, 0, 4), ">0")
plt.show()

3
Perché questa risposta è migliore di quella che utilizza plt.clim pubblicata da @Amro?
Alex Lamson,

90

Utilizzare la funzione CLIM (equivalente alla funzione CAXIS in MATLAB):

plt.pcolor(X, Y, v, cmap=cm)
plt.clim(-4,4)  # identical to caxis([-4,4]) in MATLAB
plt.show()

2
Credo che clim () ridimensiona gli assi dei colori, ma i colori stessi cambiano i valori. Il punto ad una certa frazione lungo la scala sarà dello stesso colore qualunque sia la scala, ma il valore che rappresenta cambierà.
Paul

4
Sì. Questo è il comportamento desiderato dal richiedente, quindi risolve il problema: che la scala dei colori sia identica tra i grafici.
Excalabur,

16

Non sono sicuro che questa sia la soluzione più elegante (questo è quello che ho usato), ma potresti ridimensionare i tuoi dati nell'intervallo tra 0 e 1 e quindi modificare la barra dei colori:

import matplotlib as mpl
...
ax, _ = mpl.colorbar.make_axes(plt.gca(), shrink=0.5)
cbar = mpl.colorbar.ColorbarBase(ax, cmap=cm,
                       norm=mpl.colors.Normalize(vmin=-0.5, vmax=1.5))
cbar.set_clim(-2.0, 2.0)

Con i due diversi limiti è possibile controllare l'intervallo e la legenda della barra dei colori. In questo esempio nella barra viene mostrato solo un intervallo compreso tra -0,5 e 1,5, mentre la mappa dei colori copre da -2 a 2 (quindi potrebbe trattarsi dell'intervallo di dati che si registra prima del ridimensionamento).

Quindi, invece di ridimensionare la mappa dei colori, ridimensionate i vostri dati e adattate la barra dei colori a quello.


1
Penso che stia facendo qualcosa di leggermente diverso ... scusate, probabilmente non ero abbastanza preciso nella mia domanda. La tua soluzione ridimensionerà i colori in modo che ciò che era solito rappresentare il valore 1.0 ora rappresentasse il valore massimo nei miei dati. La barra dei colori mostrerà 0..1 quando ne ho bisogno (con vmin = 0, vmax = 1), ma tutto al di sopra di questo valore massimo sarà dello stesso colore ...
Paul

1
... Ho aggiornato la mia domanda per mostrare cosa sto cercando più chiaramente. Scusa se ero troppo vago.
Paul,

10

Utilizzo di figure environment e .set_clim ()

Potrebbe essere più semplice e sicura questa alternativa se hai più grafici:

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )
data1 = np.clip(data,0,6)
data2 = np.clip(data,-6,0)
vmin = np.min(np.array([data,data1,data2]))
vmax = np.max(np.array([data,data1,data2]))

fig = plt.figure()
ax = fig.add_subplot(131)
mesh = ax.pcolormesh(data, cmap = cm)
mesh.set_clim(vmin,vmax)
ax1 = fig.add_subplot(132)
mesh1 = ax1.pcolormesh(data1, cmap = cm)
mesh1.set_clim(vmin,vmax)
ax2 = fig.add_subplot(133)
mesh2 = ax2.pcolormesh(data2, cmap = cm)
mesh2.set_clim(vmin,vmax)
# Visualizing colorbar part -start
fig.colorbar(mesh,ax=ax)
fig.colorbar(mesh1,ax=ax1)
fig.colorbar(mesh2,ax=ax2)
fig.tight_layout()
# Visualizing colorbar part -end

plt.show()

inserisci qui la descrizione dell'immagine

Una sola barra dei colori

La migliore alternativa è quindi utilizzare una singola barra dei colori per l'intera trama. Esistono diversi modi per farlo, questo tutorial è molto utile per comprendere l'opzione migliore. Preferisco questa soluzione che puoi semplicemente copiare e incollare invece della precedente parte della barra dei colori di visualizzazione del codice.

fig.subplots_adjust(bottom=0.1, top=0.9, left=0.1, right=0.8,
                    wspace=0.4, hspace=0.1)
cb_ax = fig.add_axes([0.83, 0.1, 0.02, 0.8])
cbar = fig.colorbar(mesh, cax=cb_ax)

inserisci qui la descrizione dell'immagine

PS

Suggerirei di utilizzare pcolormeshinvece che pcolorperché è più veloce (maggiori informazioni qui ).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.