0

I have dataset which consists of 50 images of size 8 x 8 flattened into arrays of size 64. Using the function imshow of matplotlib.pyplot (plt) to visualize the first 16 images (in a 4x4 grid) of the dataset.

I tried the following code:

import matplotlib.pyplot as plt

import numpy as np
data = np.random.rand(50,64) #this will simulate my data

fig=plt.figure(figsize=(8, 8)) 
    
for i in range(16):
        
   img = np.reshape(data[i:(i+1)],(8,8))
   fig.add_subplot(4, 4, i)
   plt.imshow(img)
        
plt.show()

this is the traceback:

<ipython-input-207-7af8d2013358> in plot_first_digits()
     13 
     14         img = np.reshape(X[i:(i+1)],(8,8))
---> 15         fig.add_subplot(4, 4, i)
     16         plt.imshow(img)
     17 

~/anaconda3/lib/python3.8/site-packages/matplotlib/figure.py in add_subplot(self, *args, **kwargs)
   1417                     self._axstack.remove(ax)
   1418 
-> 1419             a = subplot_class_factory(projection_class)(self, *args, **kwargs)
   1420 
   1421         return self._add_axes_internal(key, a)

~/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_subplots.py in __init__(self, fig, *args, **kwargs)
     63             else:
     64                 if num < 1 or num > rows*cols:
---> 65                     raise ValueError(
     66                         f"num must be 1 <= num <= {rows*cols}, not {num}")
     67                 self._subplotspec = GridSpec(

ValueError: num must be 1 <= num <= 16, not 0

<Figure size 576x576 with 0 Axes>
3
  • Can you share the traceback? Commented Nov 15, 2020 at 21:57
  • What is traceback? Commented Nov 15, 2020 at 21:58
  • 1
    The error that Python is returning when you run this script Commented Nov 15, 2020 at 22:06

2 Answers 2

1

From your script, we can see that the error is due to the call to plt.add_subplot() with i = 0 at the first iteration (this function only accepts positive integer arguments).

Solution 1 with fig.add_subplots

import matplotlib.pyplot as plt
import numpy as np

# simulate data
data = np.random.rand(50, 64)

# create figure
fig = plt.figure(figsize=(8, 8))

# loop over images
for i in range(16):
    print(i)
    img = np.reshape(data[i : (i + 1)], (8, 8))
    fig.add_subplot(4, 4, i + 1)
    plt.imshow(img)

# save image
plt.savefig("subplot_image")

The output image looks like:

subplots show reshaped vectors into images

Solution 2 with plt.subplots (more pythonic)

The following solution produces the same image by directly iterating the subplots generated the plt.subplots(), and the elements of the data matrix.

# create figure
fig, axes = plt.subplots(4, 4, figsize=(8, 8))

# loop over images
for ax, img in zip(axes.ravel(), data):
    ax.imshow(img.reshape(8, 8))

# save image
plt.savefig("subplot_image")
Sign up to request clarification or add additional context in comments.

Comments

1

Try using Image Grid as follows:

from mpl_toolkits.axes_grid1 import ImageGrid

def show_images(images):
  fig = plt.figure(figsize=(12., 12.))
  grid = ImageGrid(fig, 111, nrows_ncols=(1, len(images)),axes_pad=0.1)

  for ax, im in zip(grid, images):
    ax.axis('off')
    ax.imshow(im, cmap="gray")

sample_negative = ~sample1
show_images([sample1, sample_negative])

Pay close attention to the constructor. You are passing your figure, number of rows and columns how you wish to align your images. In the example above, I've aligned all images in a single row. Here is how the output looks like:

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.