Modify order of column in a 2D numpy array - python

I'm working with a 2D numpy array like this:
array = np.asarray([[1,1,1,1,1],
[2,2,2,2,2],
[3,3,3,3,3],
[4,4,4,4,4],
[5,5,5,5,5]])
I also have a 1D containing indexes to change the order of the columns of my first array.
So with this index array:
column_order = np.asarray([3,2,1,0,4])
I should have someting like this:
[[4 4 4 4 4]
[3 3 3 3 3]
[2 2 2 2 2]
[1 1 1 1 1]
[5 5 5 5 5]]
This is my code:
array = np.asarray([[1,1,1,1,1],
[2,2,2,2,2],
[3,3,3,3,3],
[4,4,4,4,4],
[5,5,5,5,5]])
column_order = np.asarray([3,2,1,0,4])
new_array = np.copy(array)
for idx , i in enumerate(column_order):
new_array[i] = array[idx]
print(new_array)
The problem is that it is a bit slow on large size array.
I would like to know if there is most efficient way to do this ?

Related

Stacked numpy arrays

I am considerably new to Python.I am willing to stack a few 1-d arrays in python and create a 2-d array using that. The arrays which I want to stack are returned from another function. The minimum reproducible code that I have written for this purpose has been shown below:
def fun1(i): # this function returns the array
return array # This array is a function of i
h0= np.empty(5,dtype=object)
arrays=[h0]
for i in range(4):
arr=fun1(i)
arrays.append(arr)
h=np.vstack(arrays)
print (h)
The desired output is of the form :
[[1 1 1 1 1]
[2 2 2 2 2]
[3 3 3 3 3]
[4 4 4 4 4]]
But I get :
[[None None None None None]
[1 1 1 1 1]
[2 2 2 2 2]
[3 3 3 3 3]
[4 4 4 4 4]]
I understand that I get the above output because an empty array of dtype=object has all elements None . But I am not being able to solve the problem. Any help regarding this would be highly appreciated.
You are getting None because you are creating an empty array with dtype object:
h0 = np.empty(5,dtype=object)
This line creates an array with None elements.
You can remove this line so that it works as you expect:
def fun1(i): # this function returns the array
return array # This array is a function of i
arrays=[]
for i in range(4):
arr=fun1(i)
arrays.append(arr)
h = np.vstack(arrays)
print (h)
if np.where(~a.any(axis=1))[0]:
#do nothing
else:
#print as you like
try this
h = np.vstack([
fun1(i)
for i in range(4)
])
print(h)
^^ this is assuming that fun1() is some proprietary function returning arrays of same length
but if you want a 2D array with equal rows entries and incrementing column-wise like
[[1 1 1 1 1]
[2 2 2 2 2]
[3 3 3 3 3]
[4 4 4 4 4]]
you can also try a faster method
x = np.arange(1,5).reshape([-1,1])
h = np.repeat(x, 5, axis= 1)

How to overwrite 2-D numpy multi times symmetrically with given index?

I'm trying to change values in matrix a with given index matrix d and matrix e.
And the matrix should always be symmetrical.
What I come up with is to overwrite the primal matrix with given index, and try to make it symmetrical, then go for another overwrite, until all the given index matrix have been gone through. It's not efficient.
But I'm stuck with how make it symmetrical.
For example:
a = np.ones([4,4],dtype=np.object) #the primal matrix
d = np.array([[1],
[2],
[0],
[0]]) #the first index matrix
a[np.arange(a.shape[0])[:,None],d] =2 #the element change to 2 with the indexes shown in d matrix
Now the result is:
a = np.array([[1 2 1 1]
[1 1 2 1]
[2 1 1 1]
[2 1 1 1]])
After making it symmetrical (if a[ i ][ j ] was selected in d matrix, a[ j ][ i ] should also be changed to 2, how to do this part).
The expected output should be :
a = np.array([[1 2 2 2]
[2 1 2 1]
[2 2 1 1]
[2 1 1 1]])
Then, for another overwrite again:
e = np.array([[0],[2],[1],[1]])
a[np.arange(a.shape[0])[:,None],e] =3
Now the result is:
a = np.array([[3 2 2 2]
[2 1 3 1]
[2 3 1 1]
[2 3 1 1]])
Make it symmetrical, (I don't know how to do this part) the final output should be : (overwrite the values if they were given 2 or 1 before)
a = np.array([[3 2 2 2]
[2 1 3 3]
[2 3 1 1]
[2 3 1 1]])
What should I do to get symmetrical matrix?
And, is there anyway to change the primal matrix a directly to get the final result? In a more efficient way?
Thanks in advance !!
You can simply switch the first and second indices and apply the change, the result would be symmetrical:
a[np.arange(a.shape[0])[:,None], d] = 2
a[d, np.arange(a.shape[0])[:,None]] = 2
output:
[[1 2 2 2]
[2 1 2 1]
[2 2 1 1]
[2 1 1 1]]
Same with any number of other changes:
a[np.arange(a.shape[0])[:,None], e] = 3
a[e, np.arange(a.shape[0])[:,None]] = 3
output:
[[3 2 2 2]
[2 1 3 3]
[2 3 1 1]
[2 3 1 1]]

Is there a way to permute a subset of a matrix?

I'm working on a way to find the lowest 1-Norm of a given Matrix using a permutation of its rows. The problem is that the permutation can't be fully random. There are 4 subsets of rows in the Matrix having a special parameter. I want to permute just the rows having this one parameter and keeping those on the same spot.
Ex. The first column defines the type of row.
A = [
1, val_11, val_12, ... #1. Row
2, val_21, val_22, ... #2. Row
2, val_31, val_32, ... #3. Row
2, val_41, val_42, ... #4. Row
1, val_51, val_52, ... #5. Row
]
So in this example I want to permute the 1. and 5. Row AND permute the 2., 3. and 4. Row keeping the Types like [1;2;2;2;1] in place.
You just have to carefully define your permutations. Fancy indexing will then do the job :
Example :
from numpy.random import randint
M0 = randint(10,size=(5,5))
after=[4,2,3,1,0]
M0 = M[after]
print(M0)
print(M)
[[4 9 3 0 0]
[3 1 7 6 0]
[6 6 5 0 9]
[0 4 7 1 3]
[0 0 1 0 6]]
[[0 0 1 0 6]
[6 6 5 0 9]
[0 4 7 1 3]
[3 1 7 6 0]
[4 9 3 0 0]]

Delimiting a region of a numpy matrix

I have a 560x560 numpy matrix, which I want to convert to a 28x28 one.
Therefore, I want to subdivide it into regions with size 16x16, calculate the mean of each such regions and put that value in a new matrix.
Now I have:
import numpy as np
oldMat = ... #I load the 560x560 matrix
newMat = np.zeros((28,28)) #Initializes the new matrix of size 28x28
for i in range(0,560, 16):
for j in range(0,560, 16): #Loops over the top left corner of each region
sum = 0
for di in range(16):
for dj in range(16): #Loops over the indices of the elements in each region
sum += oldMat[i+di, j+dj]
mean = sum/256 #Calculates the mean of the elements of each region
newMat[i][j] = mean
Is there a faster way to do this? (I'm sure there is.)
If you simply want to reshape your matrix from 2D --> 4D, then you can use np.reshape():
import numpy as np
np.random.seed(0)
data = np.random.randint(0,5,size=(6,6))
Yields:
[[4 0 3 3 3 1]
[3 2 4 0 0 4]
[2 1 0 1 1 0]
[1 4 3 0 3 0]
[2 3 0 1 3 3]
[3 0 1 1 1 0]]
Then reshape:
data.reshape((3,3,2,2))
Returns:
[[[[4 0]
[3 3]]
[[3 1]
[3 2]]
[[4 0]
[0 4]]]
[[[2 1]
[0 1]]
[[1 0]
[1 4]]
[[3 0]
[3 0]]]

Numpy extract values on the diagonal from a matrix

My question is similar(the expanded version) to this post:Numpy extract row, column and value from a matrix. In that post, I extract elements which are bigger than zero from the input matrix, now I want to extract elements on the diagonal, too. So in this case,
from numpy import *
import numpy as np
m=np.array([[0,2,4],[4,0,0],[5,4,0]])
dist=[]
index_row=[]
index_col=[]
indices=np.where(matrix>0)
index_col, index_row = indices
dist=matrix[indices]
return index_row, index_col, dist
we could get,
index_row = [1 2 0 0 1]
index_col = [0 0 1 2 2]
dist = [2 4 4 5 4]
and now this is what I want,
index_row = [0 1 2 0 1 0 1 2]
index_col = [0 0 0 1 1 2 2 2]
dist = [0 2 4 4 0 5 4 0]
I tried to edit line 8 in the original code to this,
indices=np.where(matrix>0 & matrix.diagonal)
but got this error,
How to get the result I want? Please give me some suggestions, thanks!
You can use following method:
get the mask array
fill diagonal of the mask to True
select elements where elements in mask is True
Here is the code:
m=np.array([[0,2,4],[4,0,0],[5,4,0]])
mask = m > 0
np.fill_diagonal(mask, True)
m[mask]

Categories

Resources