Multiplying arrays of different dimentions without forloop - python

I have two arrays of different dimmentions. One has size A = (100000,9) the other has B= (15,100000). I want to multiply these arrays such that I get an array of size (135,100000) where each of the nine elements of A is multiplied by each of the 15 elements of B. Is there a way to do this without using a forloop?

I'll do it for a couple of smaller matrices :-)
Couple of points to orient you as you read:
(1) my example relies on numpy, which has array slicing
(2) if x is a numpy array, x[:,i] means the ith column of x
(3) itertools.product(items1, items2) returns an iterable object over the cartesian product of the elements in items1 and items2
(4) numpy.stack(blah) stacks the numpy arrays in blah, but has to be a tuple, not a list. Hence we convert the list comprehension in the line commented [1] to a tuple.
Then we have:
import numpy as np
import itertools as it
x = np.array([
[1,2],
[2,3],
[3,4],
[5,6]
])
y = np.array([
[1,2,3],
[4,5,6],
[7,8,9],
[0,1,2]
])
cartesian = it.product(range(x.shape[1]), range(y.shape[1]))
all_cols = tuple([x[:,i] * y[:,j] for (i, j) in cartesian]) # [1]
print(np.stack(all_cols).T)
Output:

Related

Combine multiple arrays into a single nested array in Python

I would like to combine N arrays of shape (I, J) into a single array of shape (I, J, N) such that the value at (i, j, n) in the final array is equal to the value of the n-th array at (i, j).
For example, let's say I have two arrays:
arr1 = [[2,3,4],
[3,4,5]]
arr2 = [[3,4,2],
[4,3,5]]
Then the final array would look like:
arr_final == [[[2,3], [3,4], [4,2]],
[[3,4], [4,3], [5,5]]]
Or, to take a more straightforward example:
arr1 = [[0,0,0],
[0,0,0]]
arr2 = [[1,1,1],
[1,1,1]]
arr3 = [[2,2,2],
[2,2,2]]
Then the final array would look like:
arr_final == [[[0,1,2], [0,1,2], [0,1,2]],
[[0,1,2], [0,1,2], [0,1,2]]]
Is there a function in Python, or more specifically Numpy, that could help me with this?
In Numpy, you can use numpy.stack. Remember to specify the axis as -1 in order to get it to correctly compose it as you want according to your question.
import numpy as np
arr_final = np.stack([arr1, arr2, ..., arrN], axis=-1)
will produce the desired outcome.

Adding data to a newly created axis in an ndarray python

I just created a new axis to expand my array from 3d to 4d (named X), however, the 4th axis has just 1 element of type None, I want to append a 1d array(s) to the newly added 3rd axes or 4th dimension. I used the np.newaxis function to create the 4th dimension.
import numpy as np
X = np.random.rand(10,5,6)
X = X[:,:,:, np.newaxis]
s = np.random.rand(10)
To add another dimension to an array, you can use numpy.append() with an axis of 0. As an example
import numpy as np
sample_array = [[1], [2], [3]]
sample_array = np.append(sample_array, [[None]], axis=0)
print(sample_array)
Which will return
[[1]
[2]
[3]
[None]]

How to change a matrix's dimension without using reshape in Python

Below is the matrix of (3*3)
a_matrix=np.array([[2,3,5],[3,2,7],[1,4,2]])
and i want to change it to (9*1) which is
[[2],[3],[5],[3],[2],[7],[1],[4],[2]]
The problem is that i need to do this without using reshape method in numpy. BTW, below is what i did which is kind of wrong. Could anyone help me with that? BTW, **i can't use those pre-defined methods to do it, i have to implement it by my own method. **.Any help is appreciated!!!
import numpy as np
a_list=[]
a_matrix=np.array([[2,3,5],[3,2,7],[1,4,2]]) #3*3 matrix
for i in range(3):
a_list.extend(a_matrix[i,:])
a_list=np.asarray(a_list) #To convert the list to numpy array
print(a_list.T.shape) #To print the shape of transpose
--->(9,) # I want (9,1) not (9,)
Flatten it and use a list comprehension
result = np.array([[x] for x in a_matrix.ravel()])
You could use np.ravel and add a dummy axis afterwards.
l_list = a_matrix.ravel()[:,None]
EDIT:
If you want a numpy-free method:
l_list = []
for i in range(3):
for j in range(3):
# replace [i][j] with [i,j] if a_matrix
# is allowed to be a numpy array
l_list.append([a_matrix[i][j]])
If you want to have the result as a numpy array without using ravel or reshape, you could create the output array in advance
l_list = np.empty((9,1))
for i in range(3):
for j in range(3):
# replace [i][j] with [i,j] if a_matrix
# is allowed to be a numpy array
l_list[i*3 + j] = a_matrix[i][j]
A pure list operation:
In [122]: alist = [[2,3,5],[3,2,7],[1,4,2]]
In [123]: [[i] for x in alist for i in x]
Out[123]: [[2], [3], [5], [3], [2], [7], [1], [4], [2]]
Forget about the np.array stuff before or after. If you can't use reshape there's no point in talking about numpy. shape is an integral part of a numpy array, and changing it with reshape is a fundamental operation.
Here is an answer where you code the solution yourself (as per your assignments requirements).
import numpy as np
a_matrix = np.array([[2,3,5],[3,2,7],[1,4,2]])
a_list = [[elem] for row in a_matrix for elem in row]
a_list = np.asarray(a_list)
print(a_list.T.shape)
Output should be as expected.

Vectorizing a numpy array call of varying indices

I have a 2D numpy array and a list of lists of indices for which I wish to compute the sum of the corresponding 1D vectors from the numpy array. This can be easily done through a for loop or via list comprehension, but I wonder if it's possible to vectorize it. With similar code I gain about 40x speedups from the vectorization.
Here's sample code:
import numpy as np
indices = [[1,2],[1,3],[2,0,3],[1]]
array_2d = np.array([[0.5, 1.5],[1.5,2.5],[2.5,3.5],[3.5,4.5]])
soln = [np.sum(array_2d[x], axis=-1) for x in indices]
(edit): Note that the indices are not (x,y) coordinates for array_2d, instead indices[0] = [1,2] represents the first and second vectors (rows) in array_2d. The number of elements of each list in indices can be variable.
This is what I would hope to be able to do:
vectorized_soln = np.sum(array_2d[indices[:]], axis=-1)
Does anybody know if there are any ways of achieving this?
First to all, I think you have a typo in the third element of indices...
The easy way to do that is building a sub_array with two arrays of indices:
i = np.array([1,1,2])
j = np.array([2,3,?])
sub_arr2d = array_2d[i,j]
and finally, you can take the sum of sub_arr2d...

Convert a 1D array to a 2D array in numpy

I want to convert a 1-dimensional array into a 2-dimensional array by specifying the number of columns in the 2D array. Something that would work like this:
> import numpy as np
> A = np.array([1,2,3,4,5,6])
> B = vec2matrix(A,ncol=2)
> B
array([[1, 2],
[3, 4],
[5, 6]])
Does numpy have a function that works like my made-up function "vec2matrix"? (I understand that you can index a 1D array like a 2D array, but that isn't an option in the code I have - I need to make this conversion.)
You want to reshape the array.
B = np.reshape(A, (-1, 2))
where -1 infers the size of the new dimension from the size of the input array.
You have two options:
If you no longer want the original shape, the easiest is just to assign a new shape to the array
a.shape = (a.size//ncols, ncols)
You can switch the a.size//ncols by -1 to compute the proper shape automatically. Make sure that a.shape[0]*a.shape[1]=a.size, else you'll run into some problem.
You can get a new array with the np.reshape function, that works mostly like the version presented above
new = np.reshape(a, (-1, ncols))
When it's possible, new will be just a view of the initial array a, meaning that the data are shared. In some cases, though, new array will be acopy instead. Note that np.reshape also accepts an optional keyword order that lets you switch from row-major C order to column-major Fortran order. np.reshape is the function version of the a.reshape method.
If you can't respect the requirement a.shape[0]*a.shape[1]=a.size, you're stuck with having to create a new array. You can use the np.resize function and mixing it with np.reshape, such as
>>> a =np.arange(9)
>>> np.resize(a, 10).reshape(5,2)
Try something like:
B = np.reshape(A,(-1,ncols))
You'll need to make sure that you can divide the number of elements in your array by ncols though. You can also play with the order in which the numbers are pulled into B using the order keyword.
If your sole purpose is to convert a 1d array X to a 2d array just do:
X = np.reshape(X,(1, X.size))
convert a 1-dimensional array into a 2-dimensional array by adding new axis.
a=np.array([10,20,30,40,50,60])
b=a[:,np.newaxis]--it will convert it to two dimension.
There is a simple way as well, we can use the reshape function in a different way:
A_reshape = A.reshape(No_of_rows, No_of_columns)
You can useflatten() from the numpy package.
import numpy as np
a = np.array([[1, 2],
[3, 4],
[5, 6]])
a_flat = a.flatten()
print(f"original array: {a} \nflattened array = {a_flat}")
Output:
original array: [[1 2]
[3 4]
[5 6]]
flattened array = [1 2 3 4 5 6]
some_array.shape = (1,)+some_array.shape
or get a new one
another_array = numpy.reshape(some_array, (1,)+some_array.shape)
This will make dimensions +1, equals to adding a bracket on the outermost
Change 1D array into 2D array without using Numpy.
l = [i for i in range(1,21)]
part = 3
new = []
start, end = 0, part
while end <= len(l):
temp = []
for i in range(start, end):
temp.append(l[i])
new.append(temp)
start += part
end += part
print("new values: ", new)
# for uneven cases
temp = []
while start < len(l):
temp.append(l[start])
start += 1
new.append(temp)
print("new values for uneven cases: ", new)
import numpy as np
array = np.arange(8)
print("Original array : \n", array)
array = np.arange(8).reshape(2, 4)
print("New array : \n", array)

Categories

Resources