What is the difference between flatten and ravel functions in numpy?

101,904

Solution 1

The current API is that:

  • flatten always returns a copy.
  • ravel returns a view of the original array whenever possible. This isn't visible in the printed output, but if you modify the array returned by ravel, it may modify the entries in the original array. If you modify the entries in an array returned from flatten this will never happen. ravel will often be faster since no memory is copied, but you have to be more careful about modifying the array it returns.
  • reshape((-1,)) gets a view whenever the strides of the array allow it even if that means you don't always get a contiguous array.

Solution 2

As explained here a key difference is that:

  • flatten is a method of an ndarray object and hence can only be called for true numpy arrays.

  • ravel is a library-level function and hence can be called on any object that can successfully be parsed.

For example ravel will work on a list of ndarrays, while flatten is not available for that type of object.

@IanH also points out important differences with memory handling in his answer.

Solution 3

Here is the correct namespace for the functions:

Both functions return flattened 1D arrays pointing to the new memory structures.

import numpy
a = numpy.array([[1,2],[3,4]])

r = numpy.ravel(a)
f = numpy.ndarray.flatten(a)  

print(id(a))
print(id(r))
print(id(f))

print(r)
print(f)

print("\nbase r:", r.base)
print("\nbase f:", f.base)

---returns---
140541099429760
140541099471056
140541099473216

[1 2 3 4]
[1 2 3 4]

base r: [[1 2]
 [3 4]]

base f: None

In the upper example:

  • the memory locations of the results are different,
  • the results look the same
  • flatten would return a copy
  • ravel would return a view.

How we check if something is a copy? Using the .base attribute of the ndarray. If it's a view, the base will be the original array; if it is a copy, the base will be None.


Check if a2 is copy of a1

import numpy
a1 = numpy.array([[1,2],[3,4]])
a2 = a1.copy()
id(a2.base), id(a1.base)

Out:

(140735713795296, 140735713795296)
Share:
101,904
cryptomanic
Author by

cryptomanic

Updated on July 19, 2022

Comments

  • cryptomanic
    cryptomanic almost 2 years
    import numpy as np
    y = np.array(((1,2,3),(4,5,6),(7,8,9)))
    OUTPUT:
    print(y.flatten())
    [1   2   3   4   5   6   7   8   9]
    print(y.ravel())
    [1   2   3   4   5   6   7   8   9]
    

    Both function return the same list. Then what is the need of two different functions performing same job.

  • Franck Dernoncourt
    Franck Dernoncourt over 8 years
    Any idea why NumPy developers didn't stick to one function with some parameter copy=[True,False]?
  • IanH
    IanH over 8 years
    @FranckDernoncourt Great question. I have no idea. The only reason I can think of is wanting to provide an easy analog to a similar matlab command. It doesn't appear to have any precedent in numarray or numeric.
  • IanH
    IanH over 8 years
    Backcompat guarantees sometimes cause odd things like this to happen. For example: the numpy developers recently (in 1.10) added a previously implicit guarantee that ravel would return a contiguous array (a property that is very important when writing C extensions), so now the API is a.flatten() to get a copy for sure, a.ravel() to avoid most copies but still guarantee that the array returned is contiguous, and a.reshape((-1,)) to really get a view whenever the strides of the array allow it even if that means you don't always get a contiguous array.
  • Hossein
    Hossein over 7 years
    @IanH: Whats the difference between ravel and reshape then?
  • iled
    iled over 7 years
    @Hossein IanH explained it: ravelguarantees a contiguous array, and so it is not guaranteed that it returns a view; reshape always returns a view, and so it is not guaranteed that it returns a contiguous array.
  • Hossein
    Hossein over 7 years
    @iled: Thanks, then what's so important about being contiguous ? why would I want to care about that?
  • iled
    iled over 7 years
    @Hossein That would be a whole new question. Very briefly, it is much faster to read and write to a contiguous memory space. There are several questions and answers on that here on SO (nice example here), feel free to open a new one if you have any further questions.
  • Tom Pohl
    Tom Pohl over 6 years
    reshape(-1) is equivalent to reshape((-1,))
  • WestCoastProjects
    WestCoastProjects over 5 years
    thx for that info about the ravel() working on lists of ndarray's
  • Shiv Krishna Jaiswal
    Shiv Krishna Jaiswal over 5 years
    @diraria , we find that we can also pass order in "ravel" method. If it is 'C' which is default order then view of original array is returned. If is 'F' then it is a copied version of the array i.e. modification in this array is not reflected in actual array. (Not sure if this is a feature or bug :D)
  • Shiv Krishna Jaiswal
    Shiv Krishna Jaiswal over 5 years
    Update: view of original array is not possible if order is 'F' in "ravel" function.github.com/numpy/numpy/issues/12318
  • off99555
    off99555 over 5 years
    Why is it called ravel? What is the idea behind the name?
  • timtody
    timtody almost 4 years
    Not only lists of arrays but also lists of lists :)
  • prosti
    prosti over 3 years
    id(a1.base) should be the same as id(a2.base)
  • Julek
    Julek almost 3 years
    As these discussions reveal, Numpy is great, but not perfect.