Creating list of 2D matrices in Python - python

I am trying to create a list of 2d matrices, as per the illustration below:
list of 2d matrices
Basically, I want to start with a NxN matrix with all zeros and sequentially replace the 0's with 1's (as shown in the image). With each modification changing the 0's to 1's, I would like to output the matrix at that step and save it in a list or array.
For the first row of matrices in the illustration, I have this:
dim = 4
x=[]
for i in range(0,dim):
matrix = np.zeros((dim,dim))
matrix[0,i] = 1
x.append(matrix)
m0 = x[0]
m1 = x[0]+x[1]
m2 = x[0]+x[1]+x[2]
m3 = x[0]+x[1]+x[2]+x[3]
I would like to generalize this so I not only get the first row but the rest of the rows shown in the image and change the matrix size through 'dim'. I can't seem to figure this out. I'd appreciate any help with this.

This will do the job:
import numpy as np
dim = 4
x=[]
for i in range(dim):
lst=[]
matrix=np.zeros((dim,dim))
vec=np.ones(i+1)
for j in range(dim):
matrix[0:i+1,j]=vec
lst.append(np.copy(matrix))
x.append(lst)
print(x)

Related

Iterating through rows in python

I have a (68x2) matrix named shape and I am trying to iterate through all the 68 rows by placing column 0 and column 1 of shape in array B. This is then multiplied by a (3x3) transformation matrix A. Then my intent was to create a single array (which is why I used np.append) but actually all I am getting are 68 singular 2 dimensional matrices and I do not know why.
Here is my code:
import numpy as np
for row in shape:
B = np.array([[row[0]],[row[1]],[1]])
result = np.matmul(A,B)
result = np.append(result[0], result[1], axis = 0)
print(result)
Anyone know how I can fix my problem?
You can concatenate a new column onto your shape array and then multiply all your rows by the transform matrix at once using a single matrix multiplication.
result = (np.concatenate((shape, np.ones((68, 1))), axis=1) # A)[:,:2]
It's possible you need to multiply by the transpose of the transformation matrix, A.T, rather than by A itself.

simplity construction of sparse (transition) matrix

I am constructing a transition matrix from a n1 x n2 x ... x nN x nN array. For concreteness let N = 3, e.g.,
import numpy as np
# example with N = 3
n1, n2, n3 = 3, 2, 5
dim = (n1, n2, n3)
arr = np.random.random_sample(dim + (n3,))
Here arr contains transition probabilities between 2 states, where the "from"-state is indexed by the first 3 dimensions, and the "to"-state is indexed by the first 2 and the last dimension. I want to construct a transition matrix, which expresses these probabilities raveled into a sparse (n1*n2*n3) x (n1*n2*n3 matrix.
To clarify, let me provide my current approach that does what I want to do. Unfortunately, it's slow and doesn't work when N and n1, n2, ... are large. So I am looking for a more efficient way of doing the same that scales better for larger problems.
My approach
import numpy as np
from scipy import sparse as sparse
## step 1: get the index correponding to each dimension of the from and to state
# ravel axes 1 to 3 into single axis and make sparse
spmat = sparse.coo_matrix(arr.reshape(np.prod(dim), -1))
data = spmat.data
row = spmat.row
col = spmat.col
# use unravel to get idx for
row_unravel = np.array(np.unravel_index(row, dim))
col_unravel = np.array(np.unravel_index(col, n3))
## step 2: combine "to" index with rows 1 and 2 of "from"-index to get "to"-coordinates in full state space
row_unravel[-1, :] = col_unravel # first 2 dimensions of state do not change
colnew = np.ravel_multi_index(row_unravel, dim) # ravel back to 1d
## step 3: assemble transition matrix
out = sparse.coo_matrix((data, (row, colnew)), shape=(np.prod(dim), np.prod(dim)))
Final thought
I will be running this code many times. Across iterations, the data of arr may change, but the dimensions will stay the same. So one thing I could do is to save and load row and colnew from a file, skipping everything between the definition of data (line 2) and final line of my code. Do you think this would be the best approach?
Edit: One problem I see with this strategy is that if some elements of arr are zero (which is possible) then the size of data will change across iterations.
One approach that beats the one posted in the OP. Not sure if it's the most efficient.
import numpy as np
from scipy import sparse
# get col and row indices
idx = np.arange(np.prod(dim))
row = idx.repeat(dim[-1])
col = idx.reshape(-1, dim[-1]).repeat(dim[-1], axis=0).ravel()
# get the data
data = arr.ravel()
# construct the sparse matrix
out = sparse.coo_matrix((data, (row, col)), shape=(np.prod(dim), np.prod(dim)))
Two things that could be improved:
(1) if arr is sparse, the output matrix out will have zeros coded as nonzero.
(2) The approach relies on the new state being the last dimension of dim. It would be nice to generalize so that the last axis of arr can replace any of the originating axis, not just the last one.

way to create a 3d matrix of 2 vectors and 1 matrix

Hello i have a question regarding a problem I am facing in python. I was studying about tensors and I saw that each row/column of a tensor must have the same size. Is it possible to create a tensor of perhaps a 3d object or matrix where lets say we have 3 axis : x,y,z
In the x axis I want to create a vector to work as an index. So let x be from 0 to N
Then on the y axis I want to have N random integer vectors of size m (where mm
Is it possible?
My first approach was to create a big vector of Nm and a big matrix of (Nm,Nm) dimensions where i would store all my random vectors and matrices and then if I wanted to change for example the my second vector then i would have to play with the indexes. However is there another way to approach this problem with tensors or numpy that I m unaware of?
Thank you in advance for your advices
First vector, N = 3, [1,2, 3]
Second N vectors with length m, m = 2
[[4,5], [6,7], [7,8]]
So, N matrices of size (m,m)
[[[1,1], [2,2]], [[1,1], [2,2]], [[1,1], [2,2]] ]
Lets create numpy arrays from them.
import numpy as np
N = 3
m = 2
a = np.array([1,2,3])
b = np.random.randn(N, m)
c = np.random.randn(N, m, m)
You see the problem here? The last matrix c has already 3 dimensions according to your definitions.
Your argument can be simplified.
Let's say our final matrix is -
a = np.zeros((3,2,2)) # 3 dimensions, x,y,z
1) For first dimension -
a[0,:,:] = 0 # first axis, first index = 0
a[1,:,:] = 1 # first axis, 2nd index = 1
a[2,:,:] = 2 # first axis, 3rd index = 2
2) Now, we need to fill up the rest of the positions, but dimensions don't match up.
So, it's better to create separate tensors for them.

bootstrap numpy 2D array

I am trying to sample with replacement a base 2D numpy array with shape of (4,2) by rows, say 10 times. The final output should be a 3D numpy array.
Have tried the code below, it works. But is there a way to do it without the for loop?
base=np.array([[20,30],[50,60],[70,80],[10,30]])
print(np.shape(base))
nsample=10
tmp=np.zeros((np.shape(base)[0],np.shape(base)[1],10))
for i in range(nsample):
id_pick = np.random.choice(np.shape(base)[0], size=(np.shape(base)[0]))
print(id_pick)
boot1=base[id_pick,:]
tmp[:,:,i]=boot1
print(tmp)
Here's one vectorized approach -
m,n = base.shape
idx = np.random.randint(0,m,(m,nsample))
out = base[idx].swapaxes(1,2)
Basic idea is that we generate all the possible indices with np.random.randint as idx. That would an array of shape (m,nsample). We use this array to index into the input array along the first axis. Thus, it selects random rows off base. To get the final output with a shape (m,n,nsample), we need to swap last two axes.
You can use the stack function from numpy. Your code would then look like:
base=np.array([[20,30],[50,60],[70,80],[10,30]])
print(np.shape(base))
nsample=10
tmp = []
for i in range(nsample):
id_pick = np.random.choice(np.shape(base)[0], size=(np.shape(base)[0]))
print(id_pick)
boot1=base[id_pick,:]
tmp.append(boot1)
tmp = np.stack(tmp, axis=-1)
print(tmp)
Based on #Divakar 's answer, if you already know the shape of this 2D-array, you can treat it as an (8,) 1D array while bootstrapping, and then reshape it:
m, n = base.shape
flatbase = np.reshape(base, (m*n,))
idxs = np.random.choice(range(8), (numReps, m*n))
bootflats = flatbase[idx]
boots = np.reshape(flatbase, (numReps, m, n))

subtract rows one by one from numpy array

I have a 2D numpy array, A.
I want to subtract each rows, one by one, from A, and store the row-wise absolute sum in an array.
Is there a way to carry out the operation without using the for loop ? Below is the code with for loop.
import numpy as np
A = np.random.randint(5,size=(8,9))
b = np.zeros(A.shape[1]);
for i in xrange(A.shape[0]):
b = b + np.sum(np.absolute(A - A[i,:]), axis=0)
You could use broadcasting -
(np.abs(A[:,None,:] - A)).sum(axis=(0,1))
Steps :
(1) Keeping the last axis aligned get two versions of A :
Input1 (A[:,None,:]) : M x 1 x N
Input2 (A) : M x N
Get the absolution differences between these two inputs resulting in a 3D array.
(2) Sum along the first two axes for final output.

Categories

Resources