Подтвердить что ты не робот

Matplotlib: перемещение меток между тиками

Я хочу создать визуализацию матрицы путаницы, используя matplotlib. Параметры нижеуказанных методов - это метки классов (алфавит), результаты классификации являются списком списков (conf_arr) и выходным именем файла. Я доволен результатом до сих пор, с одной последней проблемой:

Я не могу центрировать метки тика оси между линиями сетки. Если передать параметр степени в метод imshow, как показано ниже, сетка выравнивается так, как мне бы хотелось. Если я прокомментирую это, сетка будет пропущена, но наклейки - это то, что я хотел бы они должны быть. Я думаю, мне нужен способ переместить метку метки между связанным тиком и следующим тиком но я не знаю, возможно ли и как это возможно.

Подводя итог, я хочу, чтобы сетка/тики была похожа на левое изображение, но метки метки позиционируется как в правильном изображении:

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

Полученное изображение выглядит следующим образом: enter image description here

4b9b3361

Ответ 1

Как вы заметили, они по умолчанию по умолчанию, и вы переопределяете поведение по умолчанию, указав extent=[0, width, height, 0].

Существует несколько способов справиться с этим. Один из них - использовать pcolor и установить, что edgecolors и linestyles выглядят как линии сетки (вам действительно нужно pcolor, а не pcolormesh, чтобы это работало). Тем не менее, вам придется изменить экстенты, чтобы получить тики в центре по умолчанию 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

В качестве альтернативы вы можете включить вспомогательную сетку и поместить ее на границы пикселей. Поскольку вы хотите фиксированные метки, мы просто установим все вручную. В противном случае a MultipleLocator имеет смысл:

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

Ответ 2

Альтернативно: попробовали ли вы im = ax.matshow(data, cmap='gray') вместо imshow()? Это также должно помещать метки метки в правильное положение.