Search code examples
pythonnumpymatplotlibimshow

Matplotlib : display array values with imshow


I'm trying to create a grid using a matplotlib function like imshow.
From this array:

[[ 1  8 13 29 17 26 10  4],
[16 25 31  5 21 30 19 15]]

I would like to plot the value as a color AND the text value itself (1,2, ...) on the same grid. This is what I have for the moment (I can only plot the color associated to each value):

from matplotlib import pyplot
import numpy as np

grid = np.array([[1,8,13,29,17,26,10,4],[16,25,31,5,21,30,19,15]])
print 'Here is the array'
print grid

fig1, (ax1, ax2)= pyplot.subplots(2, sharex = True, sharey = False)
ax1.imshow(grid, interpolation ='none', aspect = 'auto')
ax2.imshow(grid, interpolation ='bicubic', aspect = 'auto')
pyplot.show()   

Solution

  • If for any reason you have to use a different extent from the one that is provided naturally by imshow the following method (even if more contrived) does the job:

    enter image description here

    size = 4
    data = np.arange(size * size).reshape((size, size))
    
    # Limits for the extent
    x_start = 3.0
    x_end = 9.0
    y_start = 6.0
    y_end = 12.0
    
    extent = [x_start, x_end, y_start, y_end]
    
    # The normal figure
    fig = plt.figure(figsize=(16, 12))
    ax = fig.add_subplot(111)
    im = ax.imshow(data, extent=extent, origin='lower', interpolation='None', cmap='viridis')
    
    # Add the text
    jump_x = (x_end - x_start) / (2.0 * size)
    jump_y = (y_end - y_start) / (2.0 * size)
    x_positions = np.linspace(start=x_start, stop=x_end, num=size, endpoint=False)
    y_positions = np.linspace(start=y_start, stop=y_end, num=size, endpoint=False)
    
    for y_index, y in enumerate(y_positions):
        for x_index, x in enumerate(x_positions):
            label = data[y_index, x_index]
            text_x = x + jump_x
            text_y = y + jump_y
            ax.text(text_x, text_y, label, color='black', ha='center', va='center')
    
    fig.colorbar(im)
    plt.show()
    

    If you want to put other type of data and not necessarily the values that you used for the image you can modify the script above in the following way (added values after data):

    enter image description here

    size = 4
    data = np.arange(size * size).reshape((size, size))
    values = np.random.rand(size, size)
    
    # Limits for the extent
    x_start = 3.0
    x_end = 9.0
    y_start = 6.0
    y_end = 12.0
    
    extent = [x_start, x_end, y_start, y_end]
    
    # The normal figure
    fig = plt.figure(figsize=(16, 12))
    ax = fig.add_subplot(111)
    im = ax.imshow(data, extent=extent, origin='lower', interpolation='None', cmap='viridis')
    
    # Add the text
    jump_x = (x_end - x_start) / (2.0 * size)
    jump_y = (y_end - y_start) / (2.0 * size)
    x_positions = np.linspace(start=x_start, stop=x_end, num=size, endpoint=False)
    y_positions = np.linspace(start=y_start, stop=y_end, num=size, endpoint=False)
    
    for y_index, y in enumerate(y_positions):
        for x_index, x in enumerate(x_positions):
            label = values[y_index, x_index]
            text_x = x + jump_x
            text_y = y + jump_y
            ax.text(text_x, text_y, label, color='black', ha='center', va='center')
    
    fig.colorbar(im)
    plt.show()