我想使用matplotlib创建混淆矩阵的可视化。 下面显示的方法的参数是类标签(字母表), 分类结果列为列表(conf_arr)和输出文件名。 到目前为止,我对结果非常满意,最后一个问题是:
我无法使网格线之间的轴刻度标签居中。 如果我将extent参数传递给imshow方法,如下所示, 网格按照我希望的方式对齐。 如果我把它评论出来,那么网格是错位的,但标签是我想要的 他们是。 我想我需要一种方法来在关联的tick和下一个tick之间移动ticklabel 但我不知道是否以及如何做到这一点。
总结一下,我想要左图中的网格/刻度,但是需要标记 如右图所示:
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')
制作的图像如下所示:
答案 0 :(得分:19)
正如您所注意到的那样,默认情况下它们是居中的,您通过指定extent=[0, width, height, 0]
来覆盖默认行为。
有很多方法可以解决这个问题。一种方法是使用pcolor
并将边缘颜色和线条样式设置为看起来像网格线(实际上需要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()
或者,您可以打开次要网格并将其放在像素边界处。因为你想要固定标签,我们只需手动设置所有内容。否则,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()
答案 1 :(得分:1)
或者:您是否尝试过im = ax.matshow(data, cmap='gray')
而不是imshow()
?这也应该将ticklabels放在正确的位置。