Elementwise function over entries in two numpy arrays of differen shape - arrays

Let A be a numpy array of shape (a,b,c) and B a numpy array of shape (a',b,c). Let f(A_,B_) be a function that maps a numpy array A_ of shape (b,c) and a numpy array B_ of shape (b,c) to a real number. I would like to construct a numpy array C of shape (a,a') with entries given by applying f to the slices over the first indices.
The naive solution is
A=np.reshape(range(2*3*4), (2,3,4))
B=np.reshape(range(3*3*4), (3,3,4))
C=np.empty((2,3))
def f(A_,B_):
return np.prod(A_)+np.prod(B_)
for i in range(A.shape[0]):
for j in range(B.shape[0]):
C[i,j]=f(A[i],B[j])
which returns C as
[[ 0.00000000e+00, 6.47647525e+14, 3.99703747e+17],
[ 6.47647525e+14, 1.29529505e+15, 4.00351395e+17]]
I'm going to apply this to much larger arrays A,B with an f that is computationally expensive (above f is just a toy example). I usually try to avoid accessing numpy arrays elementwise but in above situation I'm not sure how to accomplish this.

For the dimensions in your example:
A2 = np.prod(A, axis=2).prod(axis=1)
B2 = np.prod(B, axis=2).prod(axis=1)
Bv, Av = np.meshgrid(B2, A2)
C2 = Av + Bv
array([[ 0, 647647525324800, 399703747322880000],
[ 647647525324800, 1295295050649600, 400351394848204800]])

Related

How to get a sub-shape of an array in Python?

Not sure the title is correct, but I have an array with shape (84,84,3) and I need to get subset of this array with shape (84,84), excluding that third dimension.
How can I accomplish this with Python?
your_array[:,:,0]
This is called slicing. This particular example gets the first 'layer' of the array. This assumes your subshape is a single layer.
If you are using numpy arrays, using slices would be a standard way of doing it:
import numpy as np
n = 3 # or any other positive integer
a = np.empty((84, 84, n))
i = 0 # i in [0, n]
b = a[:, :, i]
print(b.shape)
I recommend you have a look at this.

how to convert a tuple in to a 2D matrix

I a have tuple a with the shape of (3,1) and I would like to construct a 2D matrix X with the dimension(3,2). After X is constructed, there is a need to multiply X'*X which is supposed to be in the shape of (2,2)
enter image description here
import numpy as np
thistuple = (1, 2, 3)
arr=np.ones(shape=(len(thistuple),2))
tuple_index=0
for i in range(0,len(arr)):
for j in range(0,len(arr[0])):
if(tuple_index>=len(thistuple)):
break
arr[i][j]=thistuple[tuple_index]
tuple_index+=1
rez = arr.T
result = np.dot(rez,arr)
print(result)
The above code will work for an tuple of shape n*1 in python.

Inconsistent Results - Jupyter Numpy & Transpose

enter image description here
I am getting odd behavior with Jupyter/Numpy/Tranpose()/1D Arrays.
I found another post where transpose() will not transpose a 1D array, but in previous Jupyter notebooks, it does.
I have an example where it is inconsistent, and I do not understand:
Please see the picture attached of my jupyter notebook if 2 more or less identical arrays with 2 different outputs.
It seems it IS and IS NOT transposing the 1D array. Inconsistency is bad
outputs is (1000,) and (1,1000), why does this occur?
# GENERATE WAVEORM:
#---------------------------------------------------------------------------------------------------
N = 1000
fxc = []
fxn = []
for t in range(0,N):
fxc.append(A1*m.sin(2.0*pi*50.0*dt*t) + A2*m.sin(2.0*pi*120.0*dt*t))
fxn.append(A1*m.sin(2.0*pi*50.0*dt*t) + A2*m.sin(2.0*pi*120.0*dt*t) + 5*np.random.normal(u,std,size=1))
#---------------------------------------------------------------------------------------------------
# TAKE TRANSPOSE:
#---------------------------------
fc = np.transpose(np.array(fxc))
fn = np.transpose(np.array(fxn))
#---------------------------------
# PRINT DIMENSION:
#---------------------------------
print(fc.shape)
print(fn.shape)
#---------------------------------
Remove size=1 from your call to numpy.random.normal. Then it will return a scalar instead of a 1-d array of length 1.
For example,
In [2]: np.random.normal(0, 3, size=1)
Out[2]: array([0.47058288])
In [3]: np.random.normal(0, 3)
Out[3]: 4.350733438283539
Using size=1 in your code is a problem, because it results in fxn being a list of 1-d arrays (e.g. something like [[0.123], [-.4123], [0.9455], ...]. When NumPy converts that to an array, it has shape (N, 1). Transposing such an array results in the shape (1, N).
fxc, on the other hand, is a list of scalars (e.g. something like [0.123, 0.456, ...]). When converted to a NumPy array, it will be a 1-d array with shape (N,). NumPy's transpose operation swaps dimensions, but it does not create new dimensions, so transposing a 1-d array does nothing.

How to create a 2-dimensional unboxed array from a list of 1-dimensional ones?

Repa has fromListUnboxed that allows to create a 1-dimensional array from a list of values. But how can I create a 2-dimensional one given a list of 1-dimensional unboxed ones (of equal lengths)?
Use the reshape function: reshape :: (Shape sh1, Shape sh2, Source r1 e) => sh2 -> Array r1 sh1 e -> Array D sh2 e.
It's compile-time only (no runtime overhead).
I also stumbled upon this problem. I resolved it by converting the list of
arrays to unboxed vectors, concatenating those, and converting them back to a
repa array. Very clumsy, but that's all I could think about.
import Data.Array.Repa as R
import Data.Vector.Unboxed as V
import Prelude as P
arrs = P.replicate 5 $ fromListUnboxed (ix1 10) [0..9 :: Int]
main = print concatenatedArrs
where vectors = P.map toUnboxed arrs
concatenatedVectors = V.concat vectors
concatenatedArrs = fromUnboxed (R.ix2 5 10) concatenatedVectors

MATLAB: How to subset a multidimensional matrix using 1-D vector indices without for loops?

I am currently looking for an efficient way to slice multidimensional matrices in MATLAB. Ax an example, say I have a multidimensional matrix such as
A = rand(10,10,10)
I would like obtain a subset of this matrix (let's call it B) at certain indices along each dimension. To do this, I have access to the index vectors along each dimension:
ind_1 = [1,4,5]
ind_2 = [1,2]
ind_3 = [1,2]
Right now, I am doing this rather inefficiently as follows:
N1 = length(ind_1)
N2 = length(ind_2)
N3 = length(ind_3)
B = NaN(N1,N2,N3)
for i = 1:N1
for j = 1:N2
for k = 1:N3
B(i,j,k) = A(ind_1(i),ind_2(j),ind_3(k))
end
end
end
I suspect there is a smarter way to do this. Ideally, I'm looking for a solution that does not use for loops and could be used for an arbitrary N dimensional matrix.
Actually it's very simple:
B = A(ind_1, ind_2, ind_3);
As you see, Matlab indices can be vectors, and then the result is the Cartesian product of those vector indices. More information about Matlab indexing can be found here.
If the number of dimensions is unknown at programming time, you can define the indices in a cell aray and then expand into a comma-separated list:
ind = {[1 4 5], [1 2], [1 2]};
B = A(ind{:});
You can reference data in matrices by simply specifying the indices, like in the following example:
B = A(start:stop, :, 2);
In the example:
start:stop gets a range of data between two points
: gets all entries
2 gets only one entry
In your case, since all your indices are 1D, you could just simply use:
C = A(x_index, y_index, z_index);

Resources