Python matrix row shifting(Also column) - python

Is there any way that I can shift specific row in python? (It would be nice if numpy is used).
I want
[[1,2],
[3,4]]
to be
[[1,2],
[4,3]].
Also for the column would be nice!
[[1,2],
[3,4]]
to be
[[1,4],
[3,2]]
.
Thank you.

np.roll is your friend.
>>> import numpy as np
>>> x = np.array([[1,2],[3,4]])
>>> x
array([[1, 2],
[3, 4]])
>>> x[1]
array([3, 4])
>>> np.roll(x[1],1)
array([4, 3])
>>> x[1] = np.roll(x[1],1)
>>> x
array([[1, 2],
[4, 3]])
>>> x[1] = np.roll(x[1],1)
>>> x[:,1]
array([2, 4])
>>> x[:,1] = np.roll(x[:,1],1)
>>> x
array([[1, 4],
[3, 2]])
>>>

For the row shifting you can do:
import numpy as np
matrix = np.random.rand(5, 5)
row_no = 2
matrix[row_no, :] = np.array([matrix[row_no, -1]] + list(matrix[row_no, :-1]))
and similarly for column shifting you can simply switch the dimension orders.
import numpy as np
matrix = np.random.rand(5, 5)
col_no = 2
matrix[:, col_no] = np.array([matrix[-1, col_no]] + list(matrix[:-1, col_no]))

Related

Add elements to 2-D array

I have the following Arrays
import numpy as np
A = np.array([[1,2], [3,4]])
B = np.array([5,6])
Now I want to add the second element of A to B using the append function:
B = np.append(B, A[1])
What I want to get is:
B = np.array([[5, 6],[3,4]])
But what I get is:
B = np.array([5, 6, 3, 4])
How can I solve this? Should I use another function instead of numpy.append?
import numpy as np
A = np.array([[1,2], [3,4]])
B = np.array([[5,6]])
B = np.append(B, [A[1]], axis=0)
print(B)
Output
array([[5, 6],
[3, 4]])
This would be one of the way using np.append() specifying the axis = 0.
You can use np.stack for this instead of np.append:
>>> np.stack([B, A[1]])
array([[5, 6],
[3, 4]])
You could also add [:, None] to your two arrays and append with axis=1:
>>> np.append(B[:, None], A[1][:, None], axis=1)
array([[5, 3],
[6, 4]])

how to multiply a numpy column array of size N to row array of size N in python to get N X N matrix?

I wanted to multiply as like [1,2] * [1,2].T = [[1,2],[2,4]] using python. Is there any module function available in numpy or any other packages ?
I tried with numpy.matmul, numpy.dot and numpy.multiplication. Those aren't give much help
The multiplication should be the other way round:
>>> np.array([[1,2]]).T # np.array([[1,2]])
array([[1, 2],
[2, 4]])
If your arrays are vectors, you need to exapnd the dimensions:
>>> arr = np.array([1, 2])
>>> arr[:, None] # arr.T[None, :] # Or, arr[None, :].T # arr[None, :]
array([[1, 2],
[2, 4]])
Which is equivalent to:
>>> np.expand_dims(arr, axis=1) # np.expand_dims(arr, axis=0)
array([[1, 2],
[2, 4]])
This is needed because arr is of shape (2,) that is a 1D array.
To obtain the result you want you would need to multiply an array of shape (2,1) with (1,2) such that the resultant is (2, 2):
>>> np.expand_dims(a, axis=1) # That is adding a dimension in columns
>>> np.expand_dims(a, axis=1).shape
(2, 1)
Your version doesn't work because transpose of a 1-D array is same as the array itself.
>>> arr
array([1, 2])
>>> arr.T
array([1, 2])
If instead you had a 2D array from the start, then transpose would have worked:
>>> arr = np.array([[1, 2]])
>>> arr
array([[1, 2]])
>>> arr.T
array([[1],
[2]])

Search elements of one array in another, row-wise - Python / NumPy

For example, I have a matrix of unique elements,
a=[
[1,2,3,4],
[7,5,8,6]
]
and another unique matrix filled with elements which has appeard in the first matrix.
b=[
[4,1],
[5,6]
]
And I expect the result of
[
[3,0],
[1,3]
].
That is to say, I want to find each row elements of b which equals to some elements of a in the same row, return the indices of these elements in a.
How can i do that? Thanks.
Here's a vectorized approach -
# https://stackoverflow.com/a/40588862/ #Divakar
def searchsorted2d(a,b):
m,n = a.shape
max_num = np.maximum(a.max() - a.min(), b.max() - b.min()) + 1
r = max_num*np.arange(a.shape[0])[:,None]
p = np.searchsorted( (a+r).ravel(), (b+r).ravel() ).reshape(m,-1)
return p - n*(np.arange(m)[:,None])
def search_indices(a, b):
sidx = a.argsort(1)
a_s = np.take_along_axis(a,sidx,axis=1)
return np.take_along_axis(sidx,searchsorted2d(a_s,b),axis=1)
Sample run -
In [54]: a
Out[54]:
array([[1, 2, 3, 4],
[7, 5, 8, 6]])
In [55]: b
Out[55]:
array([[4, 1],
[5, 6]])
In [56]: search_indices(a, b)
Out[56]:
array([[3, 0],
[1, 3]])
Another vectorized one leveraging broadcasting -
In [65]: (a[:,None,:]==b[:,:,None]).argmax(2)
Out[65]:
array([[3, 0],
[1, 3]])
If you don't mind using loops, here's a quick solution using np.where:
import numpy as np
a=[[1,2,3,4],
[7,5,8,6]]
b=[[4,1],
[5,6]]
a = np.array(a)
b = np.array(b)
c = np.zeros_like(b)
for i in range(c.shape[0]):
for j in range(c.shape[1]):
_, pos = np.where(a==b[i,j])
c[i,j] = pos
print(c.tolist())
You can do it this way:
np.split(pd.DataFrame(a).where(pd.DataFrame(np.isin(a,b))).T.sort_values(by=[0,1])[::-1].unstack().dropna().reset_index().iloc[:,1].to_numpy(),len(a))
# [array([3, 0]), array([1, 3])]

Appending arrays with NumPy

Using NumPy, I want to create an n-by-2 array, by starting with an empty array, and adding on some 1-by-2 arrays.
Here's what I have tried so far:
x = np.array([1, 2])
y = np.array([3, 4])
z = np.array([])
z = np.append(z, x)
z = np.append(z, y)
However, this gives me:
z = [1, 2, 3, 4]
What I want is:
z = [[1, 2], [3, 4]]
How can I achieve this?
import numpy as np
x = np.array([1, 2])
y = np.array([3, 4])
z = np.append([x],[y], axis=0)
print(z)
>>> [[1 2]
[3 4]]
No need to create the array before appending, axis=0 will allow you to append row wise.
The previous works if z is not an array already. From then on you specify z as the original array and append the other array as such:
t = np.array([5, 6])
z = np.append(z,[t], axis=0)
print(z)
[[1 2]
[3 4]
[5 6]]
You can simply use np.array :
>>> np.array((x,y))
array([[1, 2],
[3, 4]])

Howto expand 2D NumPy array by copy bottom row and right column?

I have a 2D NumPy array and I hope to expand its size on both dimensions by copying the bottom row and right column.
For example, from 2x2:
[[0,1],
[2,3]]
to 4x4:
[[0,1,1,1],
[2,3,3,3],
[2,3,3,3],
[2,3,3,3]]
What's the best way to do it?
Thanks.
Here, the hstack and vstack functions can come in handy. For example,
In [16]: p = array(([0,1], [2,3]))
In [20]: vstack((p, p[-1], p[-1]))
Out[20]:
array([[0, 1],
[2, 3],
[2, 3],
[2, 3]])
And remembering that p.T is the transpose:
So now you can do something like the following:
In [16]: p = array(([0,1], [2,3]))
In [22]: p = vstack((p, p[-1], p[-1]))
In [25]: p = vstack((p.T, p.T[-1], p.T[-1])).T
In [26]: p
Out[26]:
array([[0, 1, 1, 1],
[2, 3, 3, 3],
[2, 3, 3, 3],
[2, 3, 3, 3]])
So the 2 lines of code should do it...
Make an empty array and copy whatever rows, columns you want into it.
def expand(a, new_shape):
x, y = a.shape
r = np.empty(new_shape, a.dtype)
r[:x, :y] = a
r[x:, :y] = a[-1:, :]
r[:x, y:] = a[:, -1:]
r[x:, y:] = a[-1, -1]
return r

Categories