﻿ Adding Different Sized/Shaped Displaced Numpy Matrices - ITCodar

# Adding Different Sized/Shaped Displaced Numpy Matrices

## Adding different sized/shaped displaced NumPy matrices

You just have to find the overlapping range, and then add the arrays using slicing.

``b1 = np.zeros((4,5))b2 = np.ones((4,3))pos_v, pos_h = 2, 3  # offsetv_range1 = slice(max(0, pos_v), max(min(pos_v + b2.shape, b1.shape), 0))h_range1 = slice(max(0, pos_h), max(min(pos_h + b2.shape, b1.shape), 0))v_range2 = slice(max(0, -pos_v), min(-pos_v + b1.shape, b2.shape))h_range2 = slice(max(0, -pos_h), min(-pos_h + b1.shape, b2.shape))b1[v_range1, h_range1] += b2[v_range2, h_range2]``

They're added in-place, but you could also create a new array. I might have missed some corner cases, though, but it seems to work fine.

## Add submatrices at certain locations

The nice thing about array slicing in numpy is you don't need the for loops that you are using. Also the reason that it is only putting the center element is because you only put a single element there (c1[c1mid,c1mid] is a single number) here is what you could do:

``    z[7:12,7:12] = c1    z[7:12,27:32] = c2    z[26:33,6:14] = c3    z[25:34,25:33] = c4``

## Apply a function to two equally shaped numpy matrices

It seems your example is already in the docs, see the bottom of https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.vectorize.html. So

``import scipy.statspearsonr = np.vectorize(scipy.stats.pearsonr, signature='(n),(n)->(),()')correlations = pearsonr(data["histograms"],regions_hist)``

should work :)

## Comparing matrices of different shapes

If I understand correctly, you are looking for the largest possible subarray that fits inside both `A` and `B`. You could just compare each dimension of `A` and `B` and take whichever is smallest:

``def largest_subarray(A, B):    dims = np.minimum(A.shape, B.shape)         # find smallest dimensions    idx = tuple(slice(None, dd) for dd in dims) # construct tuple of slice indices    return A[idx], B[idx]                       # index into A and B``

For your example arrays it will return `A[:3, :2], B[:3, :2]`.

## Aligning two binary matrices for maximum overlap

To find the maximum overlap you can use the `correlate2d` function from scipy:

``import scipyscipy.signal.correlate2d(a, b).max()``

Or you can implement it from scratch using numpy (which is a little bit tricky):

``import numpy as npfrom numpy.lib.stride_tricks import as_strideddef max_overlap(a, b):    b_p = np.pad(b, ((a.shape-1, a.shape-1), (a.shape-1, a.shape-1)), 'constant', constant_values=0)    output_shape = (b_p.shape - a.shape + 1, b_p.shape - a.shape + 1)    b_w = as_strided(b_p, shape=output_shape + a.shape,                          strides=b_p.strides*2)    c = (b_w * a).sum(axis=(2,3))    return c.max()``

## Is there a Rust ndarray equivalent for numpy arithmetic on a slice?

That can be done with the same two steps as those performed in Python: slicing, then add-assigning to a broadcast right-handed array.

``use ndarray::Array2;let mut a: Array2<f32> = Array2::zeros((100, 4));{     let mut slice = a.slice_mut(s![20.., ..]);    slice += &ArrayView::from(&[1.0, 2.0, 3.0, 4.0]);}``

Slicing is done with `slice_mut` and the `s!` macro for defining the intended range.
The outcome of a slice is a mutable array view, and so, most operations seen in `ArrayBase` are available, including arithmetic operations.
By broadcasting rules, a right-handed array of shape `` can be automatically broadcast to one of shape `[100, 4]` for the `+=` operator.

In case of other confusions in the transition from Python to Rust's `ndarray` crate, the documentation contains a guide for Python users.