Skip to content

Generalized flip #7346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/release/1.12.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ keyword argument. It can be set to False when no write operation
to the returned array is expected to avoid accidental
unpredictable writes.

Generalized ``flip``
~~~~~~~~~~~~~~~~~~~~
``flipud`` and ``fliplr`` reverse the elements of an array along axis=0 and
axis=1 respectively. The newly added ``flip`` function reverses the elements of
an array along any given axis.


Improvements
============
Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/routines.array-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Rearranging elements
.. autosummary::
:toctree: generated/

flip
fliplr
flipud
reshape
Expand Down
74 changes: 73 additions & 1 deletion numpy/lib/function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

__all__ = [
'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile',
'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp',
'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp', 'flip',
'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average',
'histogram', 'histogramdd', 'bincount', 'digitize', 'cov', 'corrcoef',
'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett',
Expand All @@ -45,6 +45,78 @@
]


def flip(m, axis):
"""
Reverse the order of elements in an array along the given axis.

The shape of the array is preserved, but the elements are reordered.

.. versionadded:: 1.12.0

Parameters
----------
m : array_like
Input array.
axis: integer
Axis in array, which entries are reversed.


Returns
-------
out : array_like
A view of `m` with the entries of axis reversed. Since a view is
returned, this operation is done in constant time.

See Also
--------
flipud : Flip an array vertically (axis=0).
fliplr : Flip an array horizontally (axis=1).

Notes
-----
flip(m, 0) is equivalent to flipud(m).
flip(m, 1) is equivalent to fliplr(m).
flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.

Examples
--------
>>> A = np.arange(8).reshape((2,2,2))
>>> A
array([[[0, 1],
[2, 3]],

[[4, 5],
[6, 7]]])

>>> flip(A, 0)
array([[[4, 5],
[6, 7]],

[[0, 1],
[2, 3]]])

>>> flip(A, 1)
array([[[2, 3],
[0, 1]],

[[6, 7],
[4, 5]]])

>>> A = np.random.randn(3,4,5)
>>> np.all(flip(A,2) == A[:,:,::-1,...])
True
"""
if not hasattr(m, 'ndim'):
m = asarray(m)
indexer = [slice(None)] * m.ndim
try:
indexer[axis] = slice(None, None, -1)
except IndexError:
raise ValueError("axis=%i is invalid for the %i-dimensional input array"
% (axis, m.ndim))
return m[tuple(indexer)]


def iterable(y):
"""
Check whether or not an object can be iterated over.
Expand Down
83 changes: 83 additions & 0 deletions numpy/lib/tests/test_function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,89 @@
from numpy.compat import long


def get_mat(n):
data = np.arange(n)
data = np.add.outer(data, data)
return data


class TestFlip(TestCase):
def test_axes(self):
self.assertRaises(ValueError, np.flip, np.ones(4), axis=1)
self.assertRaises(ValueError, np.flip, np.ones((4, 4)), axis=2)
self.assertRaises(ValueError, np.flip, np.ones((4, 4)), axis=-3)

def test_basic_lr(self):
a = get_mat(4)
b = a[:, ::-1]
assert_equal(np.flip(a, 1), b)
a = [[0, 1, 2],
[3, 4, 5]]
b = [[2, 1, 0],
[5, 4, 3]]
assert_equal(np.flip(a, 1), b)

def test_basic_ud(self):
a = get_mat(4)
b = a[::-1, :]
assert_equal(np.flip(a, 0), b)
a = [[0, 1, 2],
[3, 4, 5]]
b = [[3, 4, 5],
[0, 1, 2]]
assert_equal(np.flip(a, 0), b)

def test_3d_swap_axis0(self):
a = np.array([[[0, 1],
[2, 3]],

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can leave out the blank lines.

[[4, 5],
[6, 7]]])

b = np.array([[[4, 5],
[6, 7]],

[[0, 1],
[2, 3]]])

assert_equal(np.flip(a, 0), b)

def test_3d_swap_axis1(self):
a = np.array([[[0, 1],
[2, 3]],

[[4, 5],
[6, 7]]])

b = np.array([[[2, 3],
[0, 1]],

[[6, 7],
[4, 5]]])

assert_equal(np.flip(a, 1), b)

def test_3d_swap_axis2(self):
a = np.array([[[0, 1],
[2, 3]],

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation off here and below in b.

[[4, 5],
[6, 7]]])

b = np.array([[[1, 0],
[3, 2]],

[[5, 4],
[7, 6]]])

assert_equal(np.flip(a, 2), b)

def test_4d(self):
a = np.arange(2 * 3 * 4 * 5).reshape(2, 3, 4, 5)
for i in range(a.ndim):
assert_equal(np.flip(a, i), np.flipud(a.swapaxes(0, i)).swapaxes(i, 0))


class TestAny(TestCase):

def test_basic(self):
Expand Down
8 changes: 4 additions & 4 deletions numpy/lib/twodim_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def fliplr(m):

Notes
-----
Equivalent to A[:,::-1]. Requires the array to be at least 2-D.
Equivalent to m[:,::-1]. Requires the array to be at least 2-D.

Examples
--------
Expand All @@ -72,7 +72,7 @@ def fliplr(m):
[ 3., 0., 0.]])

>>> A = np.random.randn(2,3,5)
>>> np.all(np.fliplr(A)==A[:,::-1,...])
>>> np.all(np.fliplr(A) == A[:,::-1,...])
True

"""
Expand Down Expand Up @@ -107,7 +107,7 @@ def flipud(m):

Notes
-----
Equivalent to ``A[::-1,...]``.
Equivalent to ``m[::-1,...]``.
Does not require the array to be two-dimensional.

Examples
Expand All @@ -123,7 +123,7 @@ def flipud(m):
[ 1., 0., 0.]])

>>> A = np.random.randn(2,3,5)
>>> np.all(np.flipud(A)==A[::-1,...])
>>> np.all(np.flipud(A) == A[::-1,...])
True

>>> np.flipud([1,2])
Expand Down