Cartesian product of 2d and 1d numpy - python

I have 2d and 1d numpy and I want to join them with Cartesian product.
For example the numpy's are:
td = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
od = np.array([1,2,3])
The expected result should be:
[[1,2,3,1],
[1,2,3,2],
[1,2,3,3],
[4,5,6,1],
[4,5,6,2],
[4,5,6,3],
[7,8,9,1],
[7,8,9,2],
[7,8,9,3]]
The following code does not achieve the desired result:
import numpy as np
rslt = np.transpose([np.tile(td, len(od)), np.repeat(od , len(td))])
What needs to change?

Give this a try:
np.c_[np.repeat(td,3,axis=0),np.tile(od,3).reshape((-1,1))]
output:
array([[1, 2, 3, 1],
[1, 2, 3, 2],
[1, 2, 3, 3],
[4, 5, 6, 1],
[4, 5, 6, 2],
[4, 5, 6, 3],
[7, 8, 9, 1],
[7, 8, 9, 2],
[7, 8, 9, 3]])

Related

Forming a 3D np array from a 2D array

Let's say I have a 2D array:
L = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
I would like to make a 3D array from this, using a parameter N, such that (in this example, let's say N=4)
L2 = np.array([[[1,1,1,1],[2,2,2,2],[3,3,3,3]],
[[4,4,4,4],[5,5,5,5],[6,6,6,6]],
[[7,7,7,7],[8,8,8,8],[9,9,9,9]]])
Is there a nice way of doing this?
One option is to add another dimension, then repeat along the new dimension.
N = 4
out = L[..., None].repeat(N, axis=-1)
Output:
array([[[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]],
[[4, 4, 4, 4],
[5, 5, 5, 5],
[6, 6, 6, 6]],
[[7, 7, 7, 7],
[8, 8, 8, 8],
[9, 9, 9, 9]]])
You can use a combination of swapaxes and broadcast_to:
N = 4
L2 = np.broadcast_to(L.swapaxes(0, 1), (N, *reversed(L.shape))).swapaxes(0, 2)
Output will be as desired.

Numpy 2D to 3D array based on data in a column

Let's say I have data structured in a 2D array like this:
[[1, 3, 4, 6],
[1, 4, 8, 2],
[1, 3, 2, 9],
[2, 2, 4, 8],
[2, 4, 9, 1],
[2, 2, 9, 3]]
The first column denotes a third dimension, so I want to convert this to the following 3D array:
[[[3, 4, 6],
[4, 8, 2],
[3, 2, 9]],
[[2, 4, 8],
[4, 9, 1],
[2, 9, 3]]]
Is there a built-in numpy function to do this?
You can try code below:
import numpy as np
array = np.array([[1, 3, 4, 6],
[1, 4, 8, 2],
[1, 3, 2, 9],
[2, 2, 4, 8],
[2, 4, 9, 1],
[2, 2, 9, 3]])
array = np.delete(array, 0, 1)
array.reshape(2,3,-1)
Output
array([[[3, 4, 6],
[4, 8, 2],
[3, 2, 9]],
[[2, 4, 8],
[4, 9, 1],
[2, 9, 3]]])
However, this code can be used when you are aware of the array's shape. But if you are sure that the number of columns in the array is a multiple of 3, you can simply use code below to show the array in the desired format.
array.reshape(array.shape[0]//3,3,-3)
Use numpy array slicing with reshape function.
import numpy as np
arr = [[1, 3, 4, 6],
[1, 4, 8, 2],
[1, 3, 2, 9],
[2, 2, 4, 8],
[2, 4, 9, 1],
[2, 2, 9, 3]]
# convert the list to numpy array
arr = np.array(arr)
# remove first column from numpy array
arr = arr[:,1:]
# reshape the remaining array to desired shape
arr = arr.reshape(len(arr)//3,3,-1)
print(arr)
Output:
[[[3 4 6]
[4 8 2]
[3 2 9]]
[[2 4 8]
[4 9 1]
[2 9 3]]]
You list a non numpy array. I am unsure if you are just suggesting numpy as a means to get a non numpy result, or you are actually looking for a numpy array as result. If you don't actually need numpy, you could do something like this:
arr = [[1, 3, 4, 6],
[1, 4, 8, 2],
[1, 3, 2, 9],
[2, 2, 4, 8],
[2, 4, 9, 1],
[2, 2, 9, 3]]
# Length of the 3rd and 2nd dimension.
nz = arr[-1][0] + (arr[0][0]==0)
ny = int(len(arr)/nz)
res = [[arr[ny*z_idx+y_idx][1:] for y_idx in range(ny)] for z_idx in range(nz)]
OUTPUT:
[[[3, 4, 6], [4, 8, 2], [3, 2, 9]], [[2, 4, 8], [4, 9, 1], [2, 9, 3]]]
Note that the calculation of nz takes into account that the 3rd dimension index in your array is either 0-based (as python is per default) or 1-based (as you show in your example).

Dot product columns by rows python - numpy

I am trying to take out the dot product of each row against itself in a nx3 vector. Let me explain a little better: what I need is to go from a nx3 to a nx3x3 array.
If i have the following:
A = np.array([[1, 2, 2],
[4, 2, 3])
I would like to get what it would be:
First element:
np.dot(A[0].reshape(3,1), A[0].reshape(1,3)) = array([[1, 2, 2], [2, 4, 4], [2, 4, 4]])
Second element:
np.dot(A[1].reshape(3,1), A[1].reshape(1,3)) = array([[16, 8, 12], [8, 4, 6], [12, 6, 9]])
So my final array would be:
result = array([[[ 1, 2, 2],
[ 2, 4, 4],
[ 2, 4, 4]],
[[16, 8, 12],
[ 8, 4, 6],
[12, 6, 9]])
result.shape = (2, 3, 3)
I know I can do this with a for loop but I guess there must be a way to do it faster and more directly. Speed is vital for what I need.
Hope I explained myself correctly enough. Thank you in advance.
In [301]: A = np.array([[1, 2, 2],
...: [4, 2, 3]])
...:
...:
This isn't a dot product; there's no summing of products. Rather it's more like an outer product, increasing the number of dimensions. numpy with broadcasting does this nicely:
In [302]: A[:,:,None]*A[:,None,:]
Out[302]:
array([[[ 1, 2, 2],
[ 2, 4, 4],
[ 2, 4, 4]],
[[16, 8, 12],
[ 8, 4, 6],
[12, 6, 9]]])

Flattening an array of matrices to a single matrix (python)

I have a list of matrices:
arr = [array([[1, 2, 3], [7, 8, 9]]), array([[4, 5, 6], [0, 0, 1]])]
I want to flatten them in the following way:
[[1, 2, 3], [7, 8, 9], [4, 5, 6], [0, 0, 1]]
numpy.flatten flattens it into a single array of numbers.
I tried this: flattened_list = [y for x in arr for y in x]
It does the job, but all rows of the matrix are numpy arrays.
Is there any way to flatten numpy arrays upto a certain depth?
You should use reshape:
out = arr.reshape((4,3))
What you want is the vstack function from numpy. It takes a tuple of ndarrays and returns a new ndarray which is the result of stacking them vertically with the first ndarray being on top and so on.
For example:
import numpy as np
>>> a = np.array([1, 2])
>>> b = np.array([3, 4])
>>> c = np.array([5, 6])
>>> np.vstack(a, b)
array([[1, 2],
[3, 4],
[5, 6]])
In your case you can easily call the tuple function on your list of ndarrays
>>> arr = [array([[1, 2, 3], [7, 8, 9]]), array([[4, 5, 6], [0, 0, 1]])]
>>> np.vstack(tuple(arr))
array([[1, 2, 3],
[7, 8, 9],
[4, 5, 6],
[0, 0, 1]])
If you want your answer as a python list then just call numpy's ndarray.tolist function on the result like so:
>>> np.ndarray.tolist(np.vstack(arr))
[[1, 2, 3], [7, 8, 9], [4, 5, 6], [0, 0, 1]]

Delete items in subarrays of a master array

let's say I have the following 3x4 array
master_array = [[1, 3, 4, 5],
[6, 5, 4, 1],
[7, 8, 4, 1]]
Then, I want to delete number 4 from each of the 3 1x4 subarrays. Would I use the following?
for i in range(master_array.shape[0]):
np.delete(master_array[i], 3)
Then, when I print the master_array, would I get?
[[1, 3, 5],
[6, 5, 1],
[7, 8, 1]]
In case master_array is a list of lists, like in your example, you could do
master_array = [[1, 3, 4, 5],
[6, 5, 4, 1],
[7, 8, 4, 1]]
for row in master_array:
del row[2]
In case master_array is indeed a numpy array, you would simply do
master_array = np.array([[1, 3, 4, 5],
[6, 5, 4, 1],
[7, 8, 4, 1]])
np.delete(master_array, 2, axis=1)

Categories