how can I do 2d 3d multiplication - python

I have two array one is 3d :
np.array([[[1,2,3],[3,2,1]],
[[2,3,2],[1,2,5]]])
and one 2d array :
np.array([[2,3],
[3,4]])
and I want to multiply these two to get
np.array([[[2,4,6],[9,6,3]],
[[6,9,6],[4,8,20]]])
How can I do this using numpy package? Thanks.

Use broadcasting:
In [129]: b[:,:,None] * a
Out[129]:
array([[[ 2, 4, 6],
[ 9, 6, 3]],
[[ 6, 9, 6],
[ 4, 8, 20]]])

With following names:
main = np.array([[[1,2,3],[3,2,1]],
[[2,3,2],[1,2,5]]])
fac = np.array([[2,3],
[3,4]])
It can managed with iteration as follows:
a1 = []
for i in [0,1]:
a2 = []
for j in [0,1]:
a2.append(main[i][j]*fac[i][j])
a1.append(a2)
print(a1)
Output:
[[array([2, 4, 6]), array([9, 6, 3])], [array([6, 9, 6]), array([ 4, 8, 20])]]

Related

transfer 3D NumPy array into a 2D NumPy array

let's say a NumPy array
a = np.array(
[[[1,2,3],
[4,5,6]],
[[7,8,9],
[10,11,12]]])
the shape will be like (2,2,3).
I'd like to make it look like this:
a = np.array(
[[1,2,3],
[7,8,9],
[4,5,6],
[10,11,12]]
)
which shape will be like (4,3).
if I use reshape, it will look like as:
a = np.array(
[[1,2,3],
[4,5,6],
[7,8,9],
[10,11,12]]
)
Which is NOT what I want. How to do this?
One way using numpy.stack and vstack:
np.vstack(np.stack(a, 1))
Output:
array([[ 1, 2, 3],
[ 7, 8, 9],
[ 4, 5, 6],
[10, 11, 12]])
By using indexing method, an idx list could be created that specifies which indices of the ex a must be placed as which indices in the new one i.e. idx is a rearranging list:
idx = [0, 2, 1, 3]
a = a.reshape(4, 3)[idx]
a is firstly reshaped to the intended shape, which is (4,3), and then rearranged by the idx. idx[1] = 2 is showing that value in index = 2 of the ex a will be replaced to index = 1 in the new a.
Here is a more pythonic version of your problem.
This uses concatenate so append the rows of your array.
a = np.array(
[[[1,2,3],
[4,5,6]],
[[7,8,9],
[10,11,12]]]
)
def transform_2d(a_arr):
nrow = len(a[:])
all = a_arr[:,0]
for i in range(1,nrow):
all = np.concatenate((all, a_arr[:,i] ))
return all
print(transform_2d(a))
First use transpose (or swapaxes) to bring the desire rows together:
In [268]: a.transpose(1,0,2)
Out[268]:
array([[[ 1, 2, 3],
[ 7, 8, 9]],
[[ 4, 5, 6],
[10, 11, 12]]])
then the reshape follows:
In [269]: a.transpose(1,0,2).reshape(-1,3)
Out[269]:
array([[ 1, 2, 3],
[ 7, 8, 9],
[ 4, 5, 6],
[10, 11, 12]])

convert pandas series into a set of rows in dataframe every sliding window [duplicate]

Lets say I have a Python Numpy array a.
a = numpy.array([1,2,3,4,5,6,7,8,9,10,11])
I want to create a matrix of sub sequences from this array of length 5 with stride 3. The results matrix hence will look as follows:
numpy.array([[1,2,3,4,5],[4,5,6,7,8],[7,8,9,10,11]])
One possible way of implementing this would be using a for-loop.
result_matrix = np.zeros((3, 5))
for i in range(0, len(a), 3):
result_matrix[i] = a[i:i+5]
Is there a cleaner way to implement this in Numpy?
Approach #1 : Using broadcasting -
def broadcasting_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
return a[S*np.arange(nrows)[:,None] + np.arange(L)]
Approach #2 : Using more efficient NumPy strides -
def strided_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
n = a.strides[0]
return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S*n,n))
Sample run -
In [143]: a
Out[143]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [144]: broadcasting_app(a, L = 5, S = 3)
Out[144]:
array([[ 1, 2, 3, 4, 5],
[ 4, 5, 6, 7, 8],
[ 7, 8, 9, 10, 11]])
In [145]: strided_app(a, L = 5, S = 3)
Out[145]:
array([[ 1, 2, 3, 4, 5],
[ 4, 5, 6, 7, 8],
[ 7, 8, 9, 10, 11]])
Starting in Numpy 1.20, we can make use of the new sliding_window_view to slide/roll over windows of elements.
And coupled with a stepping [::3], it simply becomes:
from numpy.lib.stride_tricks import sliding_window_view
# values = np.array([1,2,3,4,5,6,7,8,9,10,11])
sliding_window_view(values, window_shape = 5)[::3]
# array([[ 1, 2, 3, 4, 5],
# [ 4, 5, 6, 7, 8],
# [ 7, 8, 9, 10, 11]])
where the intermediate result of the sliding is:
sliding_window_view(values, window_shape = 5)
# array([[ 1, 2, 3, 4, 5],
# [ 2, 3, 4, 5, 6],
# [ 3, 4, 5, 6, 7],
# [ 4, 5, 6, 7, 8],
# [ 5, 6, 7, 8, 9],
# [ 6, 7, 8, 9, 10],
# [ 7, 8, 9, 10, 11]])
Modified version of #Divakar's code with checking to ensure that memory is contiguous and that the returned array cannot be modified. (Variable names changed for my DSP application).
def frame(a, framelen, frameadv):
"""frame - Frame a 1D array
a - 1D array
framelen - Samples per frame
frameadv - Samples between starts of consecutive frames
Set to framelen for non-overlaping consecutive frames
Modified from Divakar's 10/17/16 11:20 solution:
https://stackoverflow.com/questions/40084931/taking-subarrays-from-numpy-array-with-given-stride-stepsize
CAVEATS:
Assumes array is contiguous
Output is not writable as there are multiple views on the same memory
"""
if not isinstance(a, np.ndarray) or \
not (a.flags['C_CONTIGUOUS'] or a.flags['F_CONTIGUOUS']):
raise ValueError("Input array a must be a contiguous numpy array")
# Output
nrows = ((a.size-framelen)//frameadv)+1
oshape = (nrows, framelen)
# Size of each element in a
n = a.strides[0]
# Indexing in the new object will advance by frameadv * element size
ostrides = (frameadv*n, n)
return np.lib.stride_tricks.as_strided(a, shape=oshape,
strides=ostrides, writeable=False)

How can I merge rows in np matrix?

I've got a numpy matrix that has 2 rows and N columns, e.g. (if N=4):
[[ 1 3 5 7]
[ 2 4 6 8]]
The goal is create a string 1,2,3,4,5,6,7,8.
Merge the rows such that the elements from the first row have the even (1, 3, ..., N - 1) positions (the index starts from 1) and the elements from the second row have the odd positions (2, 4, ..., N).
The following code works but it isn't really nice:
xs = []
for i in range(number_of_cols):
xs.append(nums.item(0, i))
ys = []
for i in range(number_of_cols):
ys.append(nums.item(1, i))
nums_str = ""
for i in range(number_of_cols):
nums_str += '{},{},'.format(xs[i], ys[i])
Join the result list with a comma as a delimiter (row.join(','))
How can I merge the rows using built in functions (or just in a more elegant way overall)?
Specify F order when flattening (or ravel):
In [279]: arr = np.array([[1,3,5,7],[2,4,6,8]])
In [280]: arr
Out[280]:
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
In [281]: arr.ravel(order='F')
Out[281]: array([1, 2, 3, 4, 5, 6, 7, 8])
Joining rows can be done this way :
>>> a = np.arange(12).reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> np.hstack([a[i,:] for i in range(a.shape[0])])
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Then it's simple to convert this array into string.
Here's one way of doing it:
out_str = ','.join(nums.T.ravel().astype('str'))
We are first transposing the array with .T, then flattening it with .ravel(), then converting each element from int to str, and then applying `','.join() to combine all the str elements
Trying it out:
import numpy as np
nums = np.array([[1,3,5,7],[2,4,6,8]])
out_str = ','.join(nums.T.ravel().astype('str'))
print (out_str)
Result:
1,2,3,4,5,6,7,8

slice matrix by different index arrary

I have a, ex 5*3 array such as
[1,2,3]
[4,5,6]
[7,8,9]
[10,11,12]
[13,14,15]
and I have 3 list to select them, ex
a1 = [0,1,2]
a2 = [0,1,3]
a3 = [0,2,4]
Now I want to get 3 array, each comes from a for a1, a2 & a3
also, a1 selects 1st column only, a2 selects 2nd column only...
for given example, I want
[1,4,7], [2,5,11], [9,12,15]
What's the best way to do it?
Thanks.
In [913]: arr = np.arange(1,16).reshape(5,3)
In [914]: arr
Out[914]:
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12],
[13, 14, 15]])
In [915]: idx = np.array([[0,1,2],[0,1,3],[0,2,4]])
In [916]: idx.shape
Out[916]: (3, 3)
We want to select a (3,3) array of values, where idx identifies rows. So we need an column index that broadcasts with it. [0,1,2] will do.
In [917]: arr[idx, np.arange(3)]
Out[917]:
array([[ 1, 5, 9],
[ 1, 5, 12],
[ 1, 8, 15]])
Oops, wrong selection; let's try the transpose:
In [918]: arr[idx.T, np.arange(3)]
Out[918]:
array([[ 1, 2, 3],
[ 4, 5, 9],
[ 7, 11, 15]])

efficient way to rebuild np.array based on a moving slicing of a np.array [duplicate]

Lets say I have a Python Numpy array a.
a = numpy.array([1,2,3,4,5,6,7,8,9,10,11])
I want to create a matrix of sub sequences from this array of length 5 with stride 3. The results matrix hence will look as follows:
numpy.array([[1,2,3,4,5],[4,5,6,7,8],[7,8,9,10,11]])
One possible way of implementing this would be using a for-loop.
result_matrix = np.zeros((3, 5))
for i in range(0, len(a), 3):
result_matrix[i] = a[i:i+5]
Is there a cleaner way to implement this in Numpy?
Approach #1 : Using broadcasting -
def broadcasting_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
return a[S*np.arange(nrows)[:,None] + np.arange(L)]
Approach #2 : Using more efficient NumPy strides -
def strided_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
n = a.strides[0]
return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S*n,n))
Sample run -
In [143]: a
Out[143]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [144]: broadcasting_app(a, L = 5, S = 3)
Out[144]:
array([[ 1, 2, 3, 4, 5],
[ 4, 5, 6, 7, 8],
[ 7, 8, 9, 10, 11]])
In [145]: strided_app(a, L = 5, S = 3)
Out[145]:
array([[ 1, 2, 3, 4, 5],
[ 4, 5, 6, 7, 8],
[ 7, 8, 9, 10, 11]])
Starting in Numpy 1.20, we can make use of the new sliding_window_view to slide/roll over windows of elements.
And coupled with a stepping [::3], it simply becomes:
from numpy.lib.stride_tricks import sliding_window_view
# values = np.array([1,2,3,4,5,6,7,8,9,10,11])
sliding_window_view(values, window_shape = 5)[::3]
# array([[ 1, 2, 3, 4, 5],
# [ 4, 5, 6, 7, 8],
# [ 7, 8, 9, 10, 11]])
where the intermediate result of the sliding is:
sliding_window_view(values, window_shape = 5)
# array([[ 1, 2, 3, 4, 5],
# [ 2, 3, 4, 5, 6],
# [ 3, 4, 5, 6, 7],
# [ 4, 5, 6, 7, 8],
# [ 5, 6, 7, 8, 9],
# [ 6, 7, 8, 9, 10],
# [ 7, 8, 9, 10, 11]])
Modified version of #Divakar's code with checking to ensure that memory is contiguous and that the returned array cannot be modified. (Variable names changed for my DSP application).
def frame(a, framelen, frameadv):
"""frame - Frame a 1D array
a - 1D array
framelen - Samples per frame
frameadv - Samples between starts of consecutive frames
Set to framelen for non-overlaping consecutive frames
Modified from Divakar's 10/17/16 11:20 solution:
https://stackoverflow.com/questions/40084931/taking-subarrays-from-numpy-array-with-given-stride-stepsize
CAVEATS:
Assumes array is contiguous
Output is not writable as there are multiple views on the same memory
"""
if not isinstance(a, np.ndarray) or \
not (a.flags['C_CONTIGUOUS'] or a.flags['F_CONTIGUOUS']):
raise ValueError("Input array a must be a contiguous numpy array")
# Output
nrows = ((a.size-framelen)//frameadv)+1
oshape = (nrows, framelen)
# Size of each element in a
n = a.strides[0]
# Indexing in the new object will advance by frameadv * element size
ostrides = (frameadv*n, n)
return np.lib.stride_tricks.as_strided(a, shape=oshape,
strides=ostrides, writeable=False)

Categories