2014-02-11 5 views
12

Я пытаюсь создать сетку 10x10, используя либо imshow, либо matshow в Matplotlib. Нижеприведенная функция берет в качестве входного значения массив numpy и отображает сетку. Тем не менее, я хотел бы иметь значения из массива, также отображаемые внутри ячеек, определенных сеткой. До сих пор я не мог найти правильный способ сделать это. Я могу использовать plt.text для размещения вещей по сетке, но для этого требуются координаты каждой ячейки, абсолютно неудобные. Есть ли лучший способ сделать то, что я пытаюсь выполнить?Matplotlib imshow/matshow отображаемые значения на графике

Спасибо!

ПРИМЕЧАНИЕ. Код ниже не принимает значения из массива, я просто играл с plt.text.

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import colors 

board = np.zeros((10, 10)) 

def visBoard(board): 
    cmap = colors.ListedColormap(['white', 'red']) 
    bounds=[0,0.5,1] 
    norm = colors.BoundaryNorm(bounds, cmap.N) 
    plt.figure(figsize=(4,4)) 
    plt.matshow(board, cmap=cmap, norm=norm, interpolation='none', vmin=0, vmax=1) 
    plt.xticks(np.arange(0.5,10.5), []) 
    plt.yticks(np.arange(0.5,10.5), []) 
    plt.text(-0.1, 0.2, 'x') 
    plt.text(0.9, 0.2, 'o') 
    plt.text(1.9, 0.2, 'x') 
    plt.grid() 

    visBoard(board) 

Выход:

enter image description here

+1

использовать аннотацию, которая позволяет вам быть очень гибкими с тем, как вы определяете координаты текста. – tacaswell

+0

Мне было интересно, есть ли способ сделать это, не указав координаты. До сих пор я делал это вручную (возможно, не самая умная идея). Предполагая, что размер фигуры может измениться, мне придется придумать функцию, которая вычисляет правильные координаты. – marillion

ответ

21

Можете ли вы сделать что-то вроде:

import numpy as np 
import matplotlib.pyplot as plt 

fig, ax = plt.subplots() 

min_val, max_val = 0, 10 
ind_array = np.arange(min_val + 0.5, max_val + 0.5, 1.0) 
x, y = np.meshgrid(ind_array, ind_array) 

for i, (x_val, y_val) in enumerate(zip(x.flatten(), y.flatten())): 
    c = 'x' if i%2 else 'o' 
    ax.text(x_val, y_val, c, va='center', ha='center') 
#alternatively, you could do something like 
#for x_val, y_val in zip(x.flatten(), y.flatten()): 
# c = 'x' if (x_val + y_val)%2 else 'o' 

ax.set_xlim(min_val, max_val) 
ax.set_ylim(min_val, max_val) 
ax.set_xticks(np.arange(max_val)) 
ax.set_yticks(np.arange(max_val)) 
ax.grid() 

enter image description here


Edit:

Вот обновленный пример с фоном imshow.

import numpy as np 
import matplotlib.pyplot as plt 

fig, ax = plt.subplots() 

min_val, max_val, diff = 0., 10., 1. 

#imshow portion 
N_points = (max_val - min_val)/diff 
imshow_data = np.random.rand(N_points, N_points) 
ax.imshow(imshow_data, interpolation='nearest') 

#text portion 
ind_array = np.arange(min_val, max_val, diff) 
x, y = np.meshgrid(ind_array, ind_array) 

for x_val, y_val in zip(x.flatten(), y.flatten()): 
    c = 'x' if (x_val + y_val)%2 else 'o' 
    ax.text(x_val, y_val, c, va='center', ha='center') 

#set tick marks for grid 
ax.set_xticks(np.arange(min_val-diff/2, max_val-diff/2)) 
ax.set_yticks(np.arange(min_val-diff/2, max_val-diff/2)) 
ax.set_xticklabels([]) 
ax.set_yticklabels([]) 
ax.set_xlim(min_val-diff/2, max_val-diff/2) 
ax.set_ylim(min_val-diff/2, max_val-diff/2) 
ax.grid() 
plt.show() 

enter image description here

+0

Спасибо! Я попытаюсь повторить это. Я должен использовать imshow/matshow plot в качестве базы, так как он отображает карту тепла. Я планировал иметь значения на тепловой карте. Однако, я думаю, я могу наложить то, что у вас на вершине моего графика imshow/matshow. Давайте попробуем ... – marillion

+0

@marillion, Посмотрите редактирование. – wflynny

+0

Спасибо за код! Обратите внимание, что результирующее изображение может отображаться с ног на голову. Вы можете предотвратить это путем замены двух аргументов set_ylim: ax.set_ylim (bottom = max_val - diff/2, top = min_val - diff/2) –

2

Для вашего графика вы должны должны попробовать с pyplot.table:

import matplotlib.pyplot as plt 
import numpy as np 

board = np.zeros((10, 10)) 
board[0,0] = 1 
board[0,1] = -1 
board[0,2] = 1 
def visBoard(board): 
    data = np.empty(board.shape,dtype=np.str) 
    data[:,:] = ' ' 
    data[board==1.0] = 'X' 
    data[board==-1.0] = 'O' 
    plt.axis('off') 
    size = np.ones(board.shape[0])/board.shape[0] 
    plt.table(cellText=data,loc='center',colWidths=size,cellLoc='center',bbox=[0,0,1,1]) 
    plt.show() 

visBoard(board) 
+0

Есть ли способ наложить эту таблицу на график imshow/matshow? Я должен сохранить то, что будет использоваться в качестве тепловой карты. Мне просто нужно, чтобы поверх «х» наложено «сверху». – marillion

+0

Да, я могу сделать что-то вроде 'plt.график (диапазон (10), диапазон (10)) 'и я вижу график ниже таблицы, таблица как раз как другой сюжет. –

2

Некоторые разработки на код @wflynny, что делает его в функцию, которая не принимает любую матрицу независимо от того, какой размер и определяет его значения.

import numpy as np 
import matplotlib.pyplot as plt 

cols = np.random.randint(low=1,high=30) 
rows = np.random.randint(low=1,high=30) 
X = np.random.rand(rows,cols) 

def plotMat(X): 
    fig, ax = plt.subplots() 
    #imshow portion 
    ax.imshow(X, interpolation='nearest') 
    #text portion 
    diff = 1. 
    min_val = 0. 
    rows = X.shape[0] 
    cols = X.shape[1] 
    col_array = np.arange(min_val, cols, diff) 
    row_array = np.arange(min_val, rows, diff) 
    x, y = np.meshgrid(col_array, row_array) 
    for col_val, row_val in zip(x.flatten(), y.flatten()): 
     c = '+' if X[row_val.astype(int),col_val.astype(int)] < 0.5 else '-' 
     ax.text(col_val, row_val, c, va='center', ha='center') 
    #set tick marks for grid 
    ax.set_xticks(np.arange(min_val-diff/2, cols-diff/2)) 
    ax.set_yticks(np.arange(min_val-diff/2, rows-diff/2)) 
    ax.set_xticklabels([]) 
    ax.set_yticklabels([]) 
    ax.set_xlim(min_val-diff/2, cols-diff/2) 
    ax.set_ylim(min_val-diff/2, rows-diff/2) 
    ax.grid() 
    plt.show() 

plotMat(X) 
Смежные вопросы