8000 ENH: add padding options to diff by mattharrigan · Pull Request #8206 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: add padding options to diff #8206

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
Sep 26, 2018
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.16.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ Previously, a ``LinAlgError`` would be raised when an empty matrix/empty
matrices (with zero rows and/or columns) is/are passed in. Now outputs of
appropriate shapes are returned.

``np.diff`` Added kwargs prepend and append
-------------------------------------------
Add kwargs prepend and append, allowing for values to be inserted
on either end of the differences. Similar to options for ediff1d.
Allows for the inverse of cumsum easily via prepend=0

ARM support updated
-------------------
Support for ARM CPUs has been updated to accommodate 32 and 64 bit targets,
Expand Down
30 changes: 29 additions & 1 deletion numpy/lib/function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ def gradient(f, *varargs, **kwargs):
return outvals


def diff(a, n=1, axis=-1):
def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
"""
Calculate the n-th discrete difference along the given axis.

Expand All @@ -1108,6 +1108,12 @@ def diff(a, n=1, axis=-1):
axis : int, optional
The axis along which the difference is taken, default is the
last axis.
prepend, append : array_like, optional
Values to prepend or append to "a" along axis prior to
performing the difference. Scalar values are expanded to
arrays with length 1 in the direction of axis and the shape
of the input array in along all other axes. Otherwise the
dimension and shape must match "a" except along axis.
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a test verifying that ValueError is raised if the shape doesn't match?


Returns
-------
Expand Down Expand Up @@ -1176,6 +1182,28 @@ def diff(a, n=1, axis=-1):
nd = a.ndim
axis = normalize_axis_index(axis, nd)

combined = []
if prepend is not np._NoValue:
prepend = np.asanyarray(prepend)
if prepend.ndim == 0:
shape = list(a.shape)
shape[axis] = 1
prepend = np.broadcast_to(prepend, tuple(shape))
combined.append(prepend)

combined.append(a)

if append is not np._NoValue:
append = np.asanyarray(append)
if append.ndim == 0:
shape = list(a.shape)
shape[axis] = 1
append = np.broadcast_to(append, tuple(shape))
combined.append(append)

if len(combined) > 1:
a = np.concatenate(combined, axis)

slice1 = [slice(None)] * nd
slice2 = [slice(None)] * nd
slice1[axis] = slice(1, None)
Expand Down
52 changes: 52 additions & 0 deletions numpy/lib/tests/test_function_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,58 @@ def test_subclass(self):
assert_array_equal(out3.mask, [[], [], [], [], []])
assert_(type(out3) is type(x))

def test_prepend(self):
x = np.arange(5) + 1
assert_array_equal(diff(x, prepend=0), np.ones(5))
assert_array_equal(diff(x, prepend=[0]), np.ones(5))
assert_array_equal(np.cumsum(np.diff(x, prepend=0)), x)
assert_array_equal(diff(x, prepend=[-1, 0]), np.ones(6))

x = np.arange(4).reshape(2, 2)
result = np.diff(x, axis=1, prepend=0)
expected = [[0, 1], [2, 1]]
assert_array_equal(result, expected)
result = np.diff(x, axis=1, prepend=[[0], [0]])
assert_array_equal(result, expected)

result = np.diff(x, axis=0, prepend=0)
expected = [[0, 1], [2, 2]]
assert_array_equal(result, expected)
result = np.diff(x, axis=0, prepend=[[0, 0]])
assert_array_equal(result, expected)

assert_raises(ValueError, np.diff, x, prepend=np.zeros((3,3)))

assert_raises(np.AxisError, diff, x, prepend=0, axis=3)

def test_append(self):
x = np.arange(5)
result = diff(x, append=0)
expected = [1, 1, 1, 1, -4]
assert_array_equal(result, expected)
result = diff(x, append=[0])
assert_array_equal(result, expected)
result = diff(x, append=[0, 2])
expected = expected + [2]
assert_array_equal(result, expected)

x = np.arange(4).reshape(2, 2)
result = np.diff(x, axis=1, append=0)
expected = [[1, -1], [1, -3]]
assert_array_equal(result, expected)
result = np.diff(x, axis=1, append=[[0], [0]])
assert_array_equal(result, expected)

result = np.diff(x, axis=0, append=0)
expected = [[2, 2], [-2, -3]]
assert_array_equal(result, expected)
result = np.diff(x, axis=0, append=[[0, 0]])
assert_array_equal(result, expected)

assert_raises(ValueError, np.diff, x, append=np.zeros((3,3)))

assert_raises(np.AxisError, diff, x, append=0, axis=3)


class TestDelete(object):

Expand Down
0