Difference between `nditer` and `flat`, type of element

Viewed 217

I created subplots and I wanted to modify xlim for each of subplot. I wrote the following code to do that:

import numpy as np
import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 3, figsize=(20, 10))

for ax in np.nditer(axs, flags=['refs_ok']):
    ax.set_xlim(left=0.0, right=0.5)

But I am getting the following error:

AttributeError: 'numpy.ndarray' object has no attribute 'set_xlim'

I did a bit more research and ended up with using flat to achieve what I wanted in the first place. But I do not understand why nditer is not working as I would expect. To illustrate it - the following code:

import numpy as np
import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 3, figsize=(20, 10))

print("Using flat")
for ax in axs.flat:
    print(ax, type(ax))

print("Using nditer")
for ax in np.nditer(axs, flags=['refs_ok']):
    print(ax, type(ax))

gives this results:

Using flat
AxesSubplot(0.125,0.536818;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.536818;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.536818;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.125,0.125;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.125;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.125;0.227941x0.343182) <class 'matplotlib.axes._subplots.AxesSubplot'>

Using nditer
AxesSubplot(0.125,0.536818;0.227941x0.343182) <class 'numpy.ndarray'>
AxesSubplot(0.398529,0.536818;0.227941x0.343182) <class 'numpy.ndarray'>
AxesSubplot(0.672059,0.536818;0.227941x0.343182) <class 'numpy.ndarray'>
AxesSubplot(0.125,0.125;0.227941x0.343182) <class 'numpy.ndarray'>
AxesSubplot(0.398529,0.125;0.227941x0.343182) <class 'numpy.ndarray'>
AxesSubplot(0.672059,0.125;0.227941x0.343182) <class 'numpy.ndarray'>

As I understand plt.subplots return 2D array and preferred method to iterate over its elements is nditer (https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html). Why then it does not work in this case and element that I am iterating over has type <class 'numpy.ndarray'> rather than <class 'matplotlib.axes._subplots.AxesSubplot'>?

2 Answers

Iterating over an array with nditer gives you views of the original array's cells as 0-dimensional arrays. For non-object arrays, this is almost equivalent to producing scalars, since 0-dimensional arrays usually behave like scalars, but that doesn't work for object arrays.

Iterating over an object array with flat just gives you the objects directly.

@Grzegorz

If you want to get the value through nditer, use the tolist method

import numpy as np
import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 3, figsize=(20, 10))

print("Using flat")
for ax in axs.flat:
    print(ax, type(ax))

print("Using nditer")
for ax in np.nditer(axs, flags=['refs_ok']):
    b = ax.tolist()
    print(b, type(b))

gives this results:

Using flat
AxesSubplot(0.125,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.125,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
Using nditer
AxesSubplot(0.125,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.53;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.125,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.398529,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
AxesSubplot(0.672059,0.11;0.227941x0.35) <class 'matplotlib.axes._subplots.AxesSubplot'>
Related