2014-06-12 12 views
20

Chcę utworzyć wizualizację macierzy zamieszania za pomocą matplotlib. Parametry dla metod przedstawionych poniżej to etykiety klas (alfabet), wyniki klasyfikacji jako lista list (conf_arr) i nazwa pliku wyjściowego. Jestem całkiem zadowolony z dotychczasowego wyniku, z jednym ostatnim problemem:Matplotlib: Przenoszenie ticklabels między kleszczami

Nie jestem w stanie wyśrodkować etykiet podziałki osi między liniami siatki. Jeśli przekażę parametr extent do metody imshow, jak poniżej, , siatka zostanie wyrównana tak, jak chciałbym. Jeśli to skomentuję, siatka jest pomijana, ale etykiety są takie, jakie chciałbym mieć. Myślę, że potrzebuję sposobu na przeniesienie ticklabel pomiędzy skojarzonym kleszczem a następnym kleszczem , ale nie wiem, czy i jak to jest możliwe.

Podsumowując, chcę siatki/kleszcze jak w lewym obrazie, ale ticklabels ustawione jak w obrazie po prawej:

enter image description here

def create_confusion_matrix(alphabet, conf_arr, outputname): 
    norm_conf = [] 
    width = len(conf_arr) 
    height = len(conf_arr[0]) 
    for i in conf_arr: 
     a = 0 
     tmp_arr = [] 
     a = sum(i, 0) 
     for j in i: 
      tmp_arr.append(float(j)/float(a)) 
     norm_conf.append(tmp_arr) 

    fig = plt.figure(figsize=(14,14)) 
    #fig = plt.figure() 
    plt.clf() 
    ax = fig.add_subplot(111) 
    ax.set_aspect(1) 
    ax.grid(which='major') 
    res = ax.imshow(np.array(norm_conf), cmap=plt.cm.binary, 
        interpolation='none', aspect='1', vmax=1, 
        ##Commenting out this line sets labels correctly, 
        ##but the grid is off 
        extent=[0, width, height, 0] 
        ) 
    divider = make_axes_locatable(ax) 
    cax = divider.append_axes("right", size="5%", pad=0.2) 
    cb = fig.colorbar(res, cax=cax) 

    #Axes 
    ax.set_xticks(range(width)) 
    ax.set_xticklabels(alphabet, rotation='vertical') 
    ax.xaxis.labelpad = 0.5 
    ax.set_yticks(range(height)) 
    ax.set_yticklabels(alphabet, rotation='horizontal') 
    #plt.tight_layout() 
    plt.savefig(outputname, format='png') 

Wytworzony obraz wygląda tak: enter image description here

+1

Czy rozwiązanie w [to pytanie] (http://stackoverflow.com/questions/16162514/how-can-i-move-a-tick-label-onlywith-moving-correspondet-tick) działa dla Ciebie? – BrenBarn

+2

Możliwe powiązania [Wyznaczanie x znaczników między znacznikami w matplotlib] (http://stackoverflow.com/questions/17158382/centering-x-tick-labels-between-tick-marks-in-matplotlib) – M4rtini

+1

To jest wyraźnie napisane, dobrze sformułowane pytanie! (+1) Nie wiesz, dlaczego zostałeś cofnięty. –

Odpowiedz

19

Jak zauważyłeś, są one domyślnie wyśrodkowane i nadpisujesz domyślne zachowanie, określając extent=[0, width, height, 0].

Istnieje wiele sposobów, aby sobie z tym poradzić. Jedną z nich jest użycie pcolor i ustawienie edgecolors i linestyles, aby wyglądały jak linie siatki (naprawdę potrzebujesz pcolor, a nie pcolormesh, aby to działało). Musisz jednak zmienić zakres, aby domyślnie uzyskać zaznaczenie w środku jako imshow.

import matplotlib.pyplot as plt 
import numpy as np 

data = np.random.random((10,10)) 
labels = 'abcdefghij' 

fig, ax = plt.subplots() 
im = ax.pcolor(data, cmap='gray', edgecolor='black', linestyle=':', lw=1) 
fig.colorbar(im) 

# Shift ticks to be at 0.5, 1.5, etc 
for axis in [ax.xaxis, ax.yaxis]: 
    axis.set(ticks=np.arange(0.5, len(labels)), ticklabels=labels) 

plt.show() 

enter image description here

Alternatywnie, można włączyć drobne siatki i umieścić ją w granicach pikseli. Ponieważ chcesz mieć naprawione etykiety, wszystko ustawimy ręcznie. W przeciwnym razie, MultipleLocator byłoby bardziej sensowne:

import matplotlib.pyplot as plt 
import numpy as np 

data = np.random.random((10,10)) 
labels = 'abcdefghij' 

fig, ax = plt.subplots() 
im = ax.imshow(data, cmap='gray', interpolation='none') 
fig.colorbar(im) 

# Set the major ticks at the centers and minor tick at the edges 
locs = np.arange(len(labels)) 
for axis in [ax.xaxis, ax.yaxis]: 
    axis.set_ticks(locs + 0.5, minor=True) 
    axis.set(ticks=locs, ticklabels=labels) 

# Turn on the grid for the minor ticks 
ax.grid(True, which='minor') 

plt.show() 

enter image description here

+1

Dziękuję bardzo za wysiłek, to rozwiązuje mój problem doskonale! :) – feob

1

Alternatywnie: Czy próbowałeś im = ax.matshow(data, cmap='gray') zamiast imshow()? Powinno to również umiejscowić ticklabels na właściwej pozycji.

Powiązane problemy