Python: combining and rearranging arrays - python

I have two arrays:
array1=[[1,2],
[3,4],
[8,9]]
array2=[[11,12],
[13,14],
19,20]]
How can I combine the arrays to an array which looks like:
array=[([[1,11],
[3,13],
[8,19]]),
array([[[2,12],
[4,14],
[9,20]])]
Thank you in advance!

You can use np.concatenate, First output array can be created by concatenating first column of array1 and array2 along the axis =1, and similarly for second output array take second column from array1 and array2.
Use:
new_arr1 = np.concatenate((array1[:, 0:1], array2[:, 0:1]), axis = 1)
new_arr2 = np.concatenate((array1[:, 1:2], array2[:, 1:2]), axis = 1)
Output:
>>> new_arr1
array([[ 1, 11],
[ 3, 13],
[ 8, 19]])
>>> new_arr2
array([[ 2, 12],
[ 4, 14],
[ 9, 20]])
If you don't want to keep the original array we can do inplace changes which will only take extra memory for one column.
temp = array1[:, 1].copy()
array1[:, 1] = array2[:, 0]
array2[:, 0] = temp
Output:
>>> array1
array([[ 1, 11],
[ 3, 13],
[ 8, 19]])
>>> array2
array([[ 2, 12],
[ 4, 14],
[ 9, 20]])

Use this:
import numpy as np
array_new1 = np.array([[a[0],b[0]] for a,b in zip(array1,array2)])
array_new2 = np.array([[a[1],b[1]] for a,b in zip(array1,array2)])
zip function will take many iterables (lists) and iterate each elements of all iterables (lists) parallely.
So, here I just iterated over 0 indexed element of both the arrays parallelly to get new array 1. It is done using list comprehension which is just another form of using for loop.
For new array 2, I iterated over 1 indexed elements of both arrays parallelly and combined them using list comprehension.

Related

Get element from array based on list of indices

z = np.arange(15).reshape(3,5)
indexx = [0,2]
indexy = [1,2,3,4]
zz = []
for i in indexx:
for j in indexy:
zz.append(z[i][j])
Output:
zz >> [1, 2, 3, 4, 11, 12, 13, 14]
This essentially flattens the array but only keeping the elements that have indicies present in the two indices list.
This works, but it is very slow for larger arrays/list of indicies. Is there a way to speed this up using numpy?
Thanks.
Edited to show desired output.
A list of integers can be used to access the entries of interest for numpy arrays.
z[indexx][:,indexy].flatten()
x = {"apple", "banana", "cherry"}
y = {"google", "microsoft", "apple"}
z = x.intersection(y)
print(z)
z => apples
If I understand you correctly, just use Python set. And then cast it to list.
Indexing in several dimensions at once requires broadcasting the indices against each other. np.ix_ is a handy tool for doing this:
In [127]: z
Out[127]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In [128]: z[np.ix_(indexx, indexy)]
Out[128]:
array([[ 1, 2, 3, 4],
[11, 12, 13, 14]])
Converting that to 1d is a trivial ravel() task.
Look at the ix_ produces, here it's a (2,1) and (1,4) array. You can construct such arrays 'from-scratch':
In [129]: np.ix_(indexx, indexy)
Out[129]:
(array([[0],
[2]]),
array([[1, 2, 3, 4]]))

Removing rows from subarrays of a numpy array based on a condition

I have the following numpy array:
x = [[1,2],[3,4],[10,1]]
y = [[5,6],[1,8],[7,8]]
z = [[10,2],[9,10],[11,12]]
xyz = np.array([x,y,z])
I want to remove rows with value 10 in the first column of each of x, y, z within xyz. So my desired output:
array([[[ 1, 2],
[ 3, 4]],
[[ 5, 6],
[ 1, 8],
[ 7, 8]],
[[ 9, 10],
[11, 12]]], dtype=object)
I tried xyz[xyz[:,:,0]!=10] but this doesn't preserve the 3-dimensional nature of xyz. I guess I can iterate over the first dimension, slice and append to a new array but I'm looking for a simpler (possibly a one-liner) solution.
Try:
np.array([a[a[:,0]!=10] for a in xyz])
But this, due to mismatch dimension, is not really a 3D numpy array anymore.

How can I assign multiple rows and columns of one array to the same rows and columns of another array in Python?

As the title says, how do I assign multiple rows and columns of one array to the same rows and columns of another array in Python?
I want to do the following:
Kn[0, 0] = KeTrans[startPosRow, startPosCol];
Kn[0, 1] = KeTrans[startPosRow, endPosCol];
Kn[1, 0] = KeTrans[endPosRow, startPosCol];
Kn[1, 1] = KeTrans[endPosRow, endPosCol];
Kn is a 2X2 matrix and KeTrans is a 4X4.
I tried the following but with no luck.
Kn[0:1, 0:1] = KeTrans[startPosRow: endPosRow, startPosCol: endPosCol]
But they're not the same rows and columns :-) (unless startPosRow and friends have very specific values).
The problem is that the slice startPosRow:endPosRow (for example) does not mean "element startPosRow and element endPosRow". It means "elements in range(startPosRow, endPosRow)", which doesn't include endPosRow and which typically has more than two matching indices.
If you just want the four corners, you could use slices with a step size:
Kn[0:1, 0:1] = KeTrans[startPosRow:endPosRow + 1:endPosRow - startPosRow,
startPosCol:endPosCol + 1:endPosCol - startPosCol]
For multi-dimensional arrays, I highly suggest use Numpy.
import numpy as np
To create an Nth-dimensional array:
a = np.array([4,2,4],[23,4,3,2]...,[2,3,4])
The array are indexed very intuitively:
>> a[0,1]
4
You can even do slicing for the np array.
documentation of numpy multi-dimensional array: https://numpy.org/doc/stable/reference/arrays.ndarray.html
Is this what you are trying to do:
In [323]: X = np.arange(16).reshape(4,4)
In [324]: Y = np.zeros((2,2),int)
In [325]: Y[:] = X[:2,:2]
In [326]: Y
Out[326]:
array([[0, 1],
[4, 5]])
In [327]: Y[:] = X[1:3,2:]
In [328]: Y
Out[328]:
array([[ 6, 7],
[10, 11]])
For reference
In [329]: X
Out[329]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])

Construction of two dimensional numpy array from unequally shaped one dimensional arrays | Numpy

In python have three one dimensional arrays of different shapes (like the ones given below)
a0 = np.array([5,6,7,8,9])
a1 = np.array([1,2,3,4])
a2 = np.array([11,12])
I am assuming that the array a0 corresponds to an index i=0, a1 corresponds to index i=1 and a2 corresponds to i=2. With these assumptions I want to construct a new two dimensional array where the rows would correspond to indices of the arrays (i=0,1,2) and the columns would be entries of the arrays a0, a1, a2.
In the example that I have given here, I will like the two dimensional array to look like
result = np.array([ [0,5], [0,6], [0,7], [0,8], [0,9], [1,1], [1,2],\
[1,3], [1,4], [2,11], [2,12] ])
I will very appreciate to have an answer as to how I can achieve this. In the actual problem that I am working with, I am dealing more than three one dimensional arrays. So, it will be very nice if the answer gives consideration to this.
One way to do this would be a simple list comprehension:
result = np.array([[i, arr_v] for i, arr in enumerate([a0, a1, a2])
for arr_v in arr])
>>> result
array([[ 0, 5],
[ 0, 6],
[ 0, 7],
[ 0, 8],
[ 0, 9],
[ 1, 1],
[ 1, 2],
[ 1, 3],
[ 1, 4],
[ 2, 11],
[ 2, 12]])
Adressing your concern about scaling this to more arrays, you can easily add as many arrays as you wish by simply creating a list of your array names, and using that list as the argument to enumerate:
.... for i, arr in enumerate(my_list_of_arrays) ...
You can use numpy stack functions to speed up:
aa = [a0, a1, a2]
np.hstack(tuple(np.vstack((np.full(ai.shape, i), ai)) for i, ai in enumerate(aa))).T
Here's an almost vectorized approach -
L = [a0,a1,a2] # list of all arrays
lens = [len(i) for i in L] # only looping part*
out = np.dstack(( np.repeat(np.arange(len(L)), lens), np.concatenate(L)))
*The looping part is simply to get the lengths of the arrays, which should have negligible impact on the total runtime.
Sample run -
In [19]: L = [a0,a1,a2] # list of all arrays
In [20]: lens = [len(i) for i in L]
In [21]: np.dstack(( np.repeat(np.arange(len(L)), lens), np.concatenate(L)))
Out[21]:
array([[[ 0, 5],
[ 0, 6],
[ 0, 7],
[ 0, 8],
[ 0, 9],
[ 1, 1],
[ 1, 2],
[ 1, 3],
[ 1, 4],
[ 2, 11],
[ 2, 12]]])
Another way could be to avoid np.repeat and use some array-initialization + cumsum method, which would be better for large number of arrays, as shown below -
col1 = np.concatenate(L)
col0 = np.zeros(len(col1), dtype=col1.dtype)
col0[np.cumsum(lens[:-1])] = 1
out = np.dstack((col0.cumsum(), col1))
Or use np.maximum.accumulate to replace the second cumsum -
col0[np.cumsum(lens[:-1])] = np.arange(1,len(L))
out = np.dstack((np.maximum.accumulate(col0), col1))

Numpy array indexing with partial indices

I am trying to pull out a particular slice of a numpy array but don't know how to express it with a tuple of indices. Using a tuple of indices works if its length is the same as the number of dimensions:
ind = (1,2,3)
# these two values are the same
foo[1,2,3]
foo[ind]
But if I want to get a slice along one dimension the same notation doesn't work:
ind = (2,3)
# these two values are not the same
foo[:,2,3]
foo[:,ind]
# and this isn't even proper syntax
foo[:,*ind]
So is there a way to use a named tuple of indices together with slices?
Instead of using the : syntax you can explicitly create the slice object and add that to the tuple:
ind = (2, 3)
s = slice(None) # equivalent to ':'
foo[(s,) + ind] # add s to tuples
In contrast to using foo[:, ind], the result of this should be the same as foo[:,2,3].
For accessing 2D arrays...
I believe what you are suggesting should work. Be mindful that numpy arrays index starting from 0. So to pull the first and third column from the following matrix I use column indices 0 and 2.
import numpy as np
foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
ind = (0,2)
foo[:,ind]
For accessing 3D arrays...
3D numpy arrays are accessed by 3 values x[i,j,k] where "i" represents the first matrix slice, or
[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]]
from my example below. "j" represents the second matrix slice, or the rows of these matrices. And "k" represents their columns. i,j and k can be :, integer or tuple. So we can access particular slices by using two sets of named tuples as follows.
import numpy as np
foo2 = np.array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
ind1 = (1,2)
ind2 = (0,1)
foo2[:,ind1,ind2]

Categories

Resources