I would like to find a way to mimic MATLAB's ndarray in Python (very different ndarry function!)
so if I have 3 1D arrays, say i = 0:10, j = 0:11, k = 0:12, I would like to create 3 3D arrays,
I, J and K are all 3D array of size(11, 12, 13) with their values given by:
I(x,:,:) = i(x), J(:,x,:) = j(x) and K(:,:,x) = k(x)
In MATLAB this is simply:
[I, J, K] = ndarray(i,j,k)
is there something similar in Python, without reverting to loops - I can't seem to find it?
numpy.meshgrid does what you want
import numpy as np
I,J,K = np.meshgrid(range(2), range(3), range(4))
In [17]: print(f'I={I}')
I=[[[0 0 0 0]
[1 1 1 1]]
[[0 0 0 0]
[1 1 1 1]]
[[0 0 0 0]
[1 1 1 1]]]
In [19]: print(f'J={J}')
J=[[[0 0 0 0]
[0 0 0 0]]
[[1 1 1 1]
[1 1 1 1]]
[[2 2 2 2]
[2 2 2 2]]]
In [20]: print(f'K={K}')
K=[[[0 1 2 3]
[0 1 2 3]]
[[0 1 2 3]
[0 1 2 3]]
[[0 1 2 3]
[0 1 2 3]]]
or equivalently, the slightly more elegant mgrid:
I, J, K = np.mgrid[0:2,0:3,0:4]
Related
So I have a program that at some point creates random arrays and I have perform an operation which is to add rows while replacing other rows based on the values found in the rows. One of the random arrays will look something like this but keep in mind that it could randomly vary in size ranging from 3x3 up to 10x10:
0 2 0 1
1 0 0 1
1 0 2 1
2 0 1 2
For every row that has at least one value equal to 2 I need to remove/replace the row and add some more rows. The number of rows added will depend on the number of combinations possible of 0s and 1s where the number of digits is equal to the number of 2s counted in each row. Each added row will introduce one of these combinations in the positions where the 2s are located. The result that I'm looking for will look like this:
0 1 0 1 # First combination to replace 0 2 0 1
0 0 0 1 # Second combination to replace 0 2 0 1 (Only 2 combinations, only one 2)
1 0 0 1 # Stays the same
1 0 1 1 # First combination to replace 1 0 2 1
1 0 0 1 # Second combination to replace 1 0 2 1 (Only 2 combinations, only one 2)
0 0 1 0 # First combination to replace 2 0 1 2
0 0 1 1 # Second combination to replace 2 0 1 2
1 0 1 1 # Third combination to replace 2 0 1 2
1 0 1 0 # Fourth combination to replace 2 0 1 2 (4 combinations, there are two 2s)
If you know a Numpy way of accomplishing this I will be grateful.
You can try the following. Create a sample array:
import numpy as np
np.random.seed(5)
a = np.random.randint(0, 3, (4, 4))
print(a)
This gives:
[[2 1 2 2]
[0 1 0 0]
[2 0 2 0]
[0 1 1 0]]
Compute the output array:
ts = (a == 2).sum(axis=1)
r = np.hstack([np.array(np.meshgrid(*[[0, 1]] * t)).reshape(t, -1).T.ravel() for t in ts if t])
out = np.repeat(a, 2**ts, axis=0)
out[out == 2] = r
print(out)
Result:
[[0 1 0 0]
[0 1 0 1]
[1 1 0 0]
[1 1 0 1]
[0 1 1 0]
[0 1 1 1]
[1 1 1 0]
[1 1 1 1]
[0 1 0 0]
[0 0 0 0]
[1 0 0 0]
[0 0 1 0]
[1 0 1 0]
[0 1 1 0]]
Not the prettiest code but it does the job. You could clean up the itertools calls but this lets you see how it works.
import numpy as np
import itertools
X = np.array([[0, 2, 0, 1],
[1, 0, 0, 1],
[1, 0, 2, 1],
[2, 0, 1, 2]])
def add(X_,Y):
if Y.size == 0:
Y = X_
else:
Y = np.vstack((Y, X_))
return(Y)
Y = np.array([])
for i in range(len(X)):
if 2 not in X[i,:]:
Y = add(X[i,:], Y)
else:
a = np.where(X[i,:]==2)[0]
n = [[i for i in itertools.chain([1, 0])] for _ in range(len(a))]
m = list(itertools.product(*n))
for j in range(len(m)):
M = 1 * X[i,:]
u = list(m[j])
for k in range(len(a)):
M[a[k]] = u[k]
Y = add(M, Y)
print(Y)
#[[0 1 0 1]
# [0 0 0 1]
# [1 0 0 1]
# [1 0 1 1]
# [1 0 0 1]
# [1 0 1 1]
# [1 0 1 0]
# [0 0 1 1]
# [0 0 1 0]]
i want a good method to insert the one inside zeros in a cross pattern with ones on top rows and bottom rows.
import numpy as np
a = np.zeros((n,n), dtype=int)
a[0,:] = 1
a[-1,:] = 1
for i in range(1,n):
a[i,-i-1] = 1
print(a)
Output:
[[1 1 1]
[0 1 0]
[1 1 1]]
You can use np.eye and reverse the rows, then assign with slices:
a = np.eye(n, dtype=int)[::-1]
a[[0,-1]] = 1
print(a)
Output:
[[1 1 1 1]
[0 0 1 0]
[0 1 0 0]
[1 1 1 1]]
Numpy Three Four Five Dimensional Array in Python
Input 1: 3
Output 1:
[[0 1 0]
[1 1 1]
[0 1 0]]
Input 2:5
Output 1:
[[0 0 1 0 0]
[0 0 1 0 0]
[1 1 1 1 1]
[0 0 1 0 0]
[0 0 1 0 0]]
Notice that the 1s in the arrays make a shape like +.
My logic is shown below
a=np.zeros((n,n),dtype='int')
a[-3,:] = 1
a[:,-3] = 1 print(a)
This logic is only working for five dimensional array but not for three dimensional array.
can someone assist me to get the expected output for both three and five dimensional array using np.zeros & integer division //
As you can see, n//2 = 3 when n=5. So, that's the solution to your question as see here:
import numpy as np
def create_plus_matrix(n):
a = np.zeros((n,n),dtype='int')
a[-n//2,:] = 1
a[:,-n//2] = 1
return a
So, let's try it out:
>>> create_plus_matrix(3)
[[0 1 0]
[1 1 1]
[0 1 0]]
>> create_plus_matrix(5)
[[0 0 1 0 0]
[0 0 1 0 0]
[1 1 1 1 1]
[0 0 1 0 0]
[0 0 1 0 0]]
Do this
import numpy as np
def plus(size):
a = np.zeros([size,size], dtype = int)
a[int(size/2)] = np.ones(size)
for i in a:
i[int(size/2)] = 1
return a
print(plus(3)) //3 is the size
//Output
[[0 1 0]
[1 1 1]
[0 1 0]]
I have a 2-D array for example:
p = np.array([[21,2,3,1,12,13],
[4,5,6,14,15,16],
[7,8,9,17,18,19]])
b = np.argpartition(p, np.argmin(p, axis=1))[:, -2:]
com = np.ones([3,6],dtype=np.int)
com[np.arange(com.shape[0])[:,None],b] = 0
print(com)
b is the indices of top 2 values of each row in p:
b = [[0 5]
[4 5]
[4 5]]
com is np.ones matrix, the same size as p, the element whose index is same as b will change to 0.
So the result is :
com = [[0 1 1 1 1 0]
[1 1 1 1 0 0]
[1 1 1 1 0 0]]
Now I have one more constraint :
p[0:2,0:2] = [[21 2]
[4 5]]
The numbers in these area [0:2,0:2] should not be considered, so the result should be:
b = [[4 5]
[4 5]
[4 5]]
com = [[1 1 1 1 0 0]
[1 1 1 1 0 0]
[1 1 1 1 0 0]]
How can I do this ? Should I use a mask or something similarly?
Thanks in advance !
Just set the values in those slices to a low value, ensuring that they won't be among the two largest, an then use argpartition:
out = np.copy(p)
out[0:2,0:2] = -np.inf
np.argpartition(out, [-2,-1])[:, -2:]
array([[4, 5],
[4, 5],
[4, 5]])
I have a row vector A, A = [a1 a2 a3 ..... an] and I would like to create a diagonal matrix, B = diag(a1, a2, a3, ....., an) with the elements of this row vector. How can this be done in Python?
UPDATE
This is the code to illustrate the problem:
import numpy as np
a = np.matrix([1,2,3,4])
d = np.diag(a)
print (d)
the output of this code is [1], but my desired output is:
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
You can use diag method:
import numpy as np
a = np.array([1,2,3,4])
d = np.diag(a)
# or simpler: d = np.diag([1,2,3,4])
print(d)
Results in:
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
If you have a row vector, you can do this:
a = np.array([[1, 2, 3, 4]])
d = np.diag(a[0])
Results in:
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
For the given matrix in the question:
import numpy as np
a = np.matrix([1,2,3,4])
d = np.diag(a.A1)
print (d)
Result is again:
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
I suppose you could also use diagflat:
import numpy
a = np.matrix([1,2,3,4])
d = np.diagflat(a)
print (d)
Which like the diag method results in
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
but there's no need for flattening with .A1
Another solution could be:
import numpy as np
a = np.array([1,2,3,4])
d = a * np.identity(len(a))
As for performances for the various answers here, I get with timeit on 100000 repetitions:
np.array and np.diag (Marcin's answer): 2.18E-02 s
np.array and np.identity (this answer): 6.12E-01 s
np.matrix and np.diagflat (Bokee's answer): 1.00E-00 s
Assuming you are working in numpy based on your tags, this will do it:
import numpy
def make_diag( A ):
my_diag = numpy.zeroes( ( 2, 2 ) )
for i, a in enumerate( A ):
my_diag[i,i] = a
return my_diag
enumerate( LIST ) creates an iterator over the list that returns tuples like:
( 0, 1st element),
( 1, 2nd element),
...
( N-1, Nth element )