apply function n items at a time along axis

  • Last Update :
  • Techknowledgy :

This is a reduction:

numpy.add.reduceat(a, [0, 2]) >>>
   array([
      [4, 6],
      [12, 14]
   ], dtype = int32)

As long as by "larger" you mean longer in the "y" axis, you can extend:

a = numpy.array([
   [1, 2],
   [3, 4],
   [5, 6],
   [7, 8],
   [9, 10],
   [11, 12]
])
numpy.add.reduceat(a, [0, 2, 4]) >>>
   array([
      [4, 6],
      [12, 14],
      [20, 22]
   ], dtype = int32)

EDIT: actually, this works fine for "larger in both dimensions", too:

a = numpy.arange(24).reshape(6, 4)
numpy.add.reduceat(a, [0, 2, 4]) >>>
   array([
      [4, 6, 8, 10],
      [20, 22, 24, 26],
      [36, 38, 40, 42]
   ], dtype = int32)

Reshape splitting the first axis into two axes, such that the second split axis is of length n to have a 3D array and then sum along that split axis, like so -

a.reshape(a.shape[0] //n,n,a.shape[1]).sum(1)

Sample run -

In[55]: a
Out[55]:
   array([
      [2, 8, 0, 0],
      [1, 5, 3, 3],
      [6, 1, 4, 7],
      [0, 4, 0, 7],
      [8, 0, 8, 1],
      [8, 3, 3, 8]
   ])

In[56]: n = 2 # Sum every two rows

In[57]: a.reshape(a.shape[0] //n,n,a.shape[1]).sum(1)
      Out[57]:
      array([
         [3, 13, 3, 3],
         [6, 5, 4, 14],
         [16, 3, 11, 9]
      ])

How about something like this?

n = 2
# calculate the cumsum along axis 0 and take one row from every n rows
cumarr = arr.cumsum(axis = 0)[(n - 1)::n]

# calculate the difference of the resulting numpy array along axis 0
np.vstack((cumarr[0][None,: ], np.diff(cumarr, axis = 0)))

# array([
   [4, 6],
   #[12, 14]
])

Suggestion : 2

This function should accept 1-D arrays. It is applied to 1-D slices of arr along the specified axis.,Execute func1d(a, *args, **kwargs) where func1d operates on 1-D arrays and a is a 1-D slice of arr along axis.,The output array. The shape of out is identical to the shape of arr, except along the axis dimension. This axis is removed, and replaced with new dimensions equal to the shape of the return value of func1d. So if func1d returns a scalar out will have one fewer dimensions than arr.,For a function that returns a higher dimensional array, those dimensions are inserted in place of the axis dimension.

Ni, Nk = a.shape[: axis], a.shape[axis + 1: ]
for ii in ndindex(Ni):
   for kk in ndindex(Nk):
   f = func1d(arr[ii + s_[: , ] + kk])
Nj = f.shape
for jj in ndindex(Nj):
   out[ii + jj + kk] = f[jj]
Ni, Nk = a.shape[: axis], a.shape[axis + 1: ]
for ii in ndindex(Ni):
   for kk in ndindex(Nk):
   out[ii + s_[..., ] + kk] = func1d(arr[ii + s_[: , ] + kk])
>>> def my_func(a):
   ...""
"Average first and last element of a 1-D array"
""
...
return (a[0] + a[-1]) * 0.5 >>>
   b = np.array([
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9]
   ]) >>>
   np.apply_along_axis(my_func, 0, b)
array([4., 5., 6.]) >>>
   np.apply_along_axis(my_func, 1, b)
array([2., 5., 8.])
>>> b = np.array([
      [8, 1, 7],
      [4, 3, 9],
      [5, 2, 6]
   ]) >>>
   np.apply_along_axis(sorted, 1, b)
array([
   [1, 7, 8],
   [3, 4, 9],
   [2, 5, 6]
])
>>> b = np.array([
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9]
   ]) >>>
   np.apply_along_axis(np.diag, -1, b)
array([
   [
      [1, 0, 0],
      [0, 2, 0],
      [0, 0, 3]
   ],
   [
      [4, 0, 0],
      [0, 5, 0],
      [0, 0, 6]
   ],
   [
      [7, 0, 0],
      [0, 8, 0],
      [0, 0, 9]
   ]
])

Suggestion : 3

Last Updated : 28 Mar, 2022

Syntax : 

numpy.apply_along_axis(1 d_func, axis, array, * args, ** kwargs)

Parameters :  

1 d_func: the required
function to perform over 1 D array.It can only be applied in
   1 D slices of input array and that too along a particular axis.
axis: required axis along which we want input array to be sliced
array: Input array to work on *
   args: Additional arguments to 1 D_function **
   kwargs: Additional arguments to 1 D_function

Output : 

use of args: [3, 4, 5, 6, 7]

Suggestion : 4

lapply returns a list of the same length as X, each element of which is the result of applying FUN to the corresponding element of X. ,Simplification in sapply is only attempted if X has length greater than zero and if the return values from all elements of X are all of the same (positive) length. If the common length is one the result is a vector, and if greater than one is a matrix with a column corresponding to each element of X. ,Function FUN must be able to accept as input any of the elements of X. If the latter is an atomic vector, FUN will always be passed a length-one vector of the same type as X. ,Users of S4 classes should pass a list to lapply and vapply: the internal coercion is done by the as.list in the base namespace and not one defined by a user (e.g., by setting S4 methods on the base function).

Usage

lapply(X, FUN, ...)

sapply(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)

vapply(X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE)

replicate(n, expr, simplify = "array")

simplify2array(x, higher = TRUE)

Examples

require(stats);
require(graphics)

x < -list(a = 1: 10, beta = exp(-3: 3), logic = c(TRUE, FALSE, FALSE, TRUE))
# compute the list mean
for each list element
lapply(x, mean)
# median and quartiles
for each list element
lapply(x, quantile, probs = 1: 3 / 4)
sapply(x, quantile)
i39 < -sapply(3: 9, seq) # list of vectors
sapply(i39, fivenum)
vapply(i39, fivenum,
   c(Min. = 0, "1st Qu." = 0, Median = 0, "3rd Qu." = 0, Max. = 0))

# # sapply( * , "array") --artificial example(v < -structure(10 * (5: 8), names = LETTERS[1: 4]))
f2 < - function(x, y) outer(rep(x, length.out = 3), y)
   (a2 < -sapply(v, f2, y = 2 * (1: 5), simplify = "array"))
a .2 < -vapply(v, f2, outer(1: 3, 1: 5), y = 2 * (1: 5))
stopifnot(dim(a2) == c(3, 5, 4), all.equal(a2, a .2),
   identical(dimnames(a2), list(NULL, NULL, LETTERS[1: 4])))

hist(replicate(100, mean(rexp(10))))

# # use of replicate() with parameters:
   foo < - function(x = 1, y = 2) c(x, y)
# does not work: bar < - function(n, ...) replicate(n, foo(...))
bar < - function(n, x) replicate(n, foo(x = x))
bar(5, x = 3)