22

What is the difference between the following?

>>> import numpy as np
>>> arr = np.array([[[  0,   1,   2],
...                  [ 10,  12,  13]],
...                 [[100, 101, 102],
...                  [110, 112, 113]]])
>>> arr
array([[[  0,   1,   2],
        [ 10,  12,  13]],
       [[100, 101, 102],
        [110, 112, 113]]])
>>> arr.ravel()
array([  0,   1,   2,  10,  12,  13, 100, 101, 102, 110, 112, 113])
>>> arr.ravel()[0] = -1
>>> arr
array([[[ -1,   1,   2],
        [ 10,  12,  13]],
       [[100, 101, 102],
        [110, 112, 113]]])
>>> list(arr.flat)
[-1, 1, 2, 10, 12, 13, 100, 101, 102, 110, 112, 113]
>>> arr.flat[0] = 99
>>> arr
array([[[ 99,   1,   2],
        [ 10,  12,  13]],
       [[100, 101, 102],
        [110, 112, 113]]])

Other than the fact that flat returns an iterator instead of a list, they appear to be the same, since they both alter the original array in place (this is in contrast to flatten(), which returns a copy of the array). So, is there any other significant difference between flat and ravel()? If not, when would it be useful to use one instead of the other?

b_pcakes
  • 2,452
  • 3
  • 28
  • 45

1 Answers1

20

flat is an iterator. It is a separate object that just happens to give access to the array elements via indexing. Its main purpose is to be used in loops and comprehension expressions. The order it gives is the same as the one you would generally get from ravel.

Unlike the result of ravel, flat is not an ndarray, so it can not do much besides indexing the array and iterating over it. Notice that you had to call list to view the contents of the iterator. For example, arr.flat.min() would fail with an AttributeError, while arr.ravel().min() would give the same result as arr.min().

Since numpy provides so many operations that do not require explicit loops to be written, ndarray.flat, and iterators in general, are rarely used compared to ndarray.ravel().

That being said, there are situations where an iterator is preferable. If your array is large enough and you are trying to inspect all the elements one-by-one, an iterator would work well. This is especially true if you have something like a memory-mapped array that gets loaded in portions.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • 1
    Specifically `flat` produces an object of type `np.flatiter` (see its docs). Also it's implemented as an attribute of the array, not a method or function. – hpaulj Jul 13 '16 at 17:25
  • @hpaulj Technically `flat` is a property of `ndarray`, which means that it is basically a no-arg method accessed as an attribute, but really returning a new instance every time it is accessed. – Mad Physicist Jul 13 '16 at 17:34
  • 1
    `flat` (along attributes like `shape`) are defined in `numpy` `c` code, and don't actually use the Python `property` mechanism`: `numpy/core/src/multiarray/getset.c`. Functionally they look similar. – hpaulj Jul 13 '16 at 19:21