List of arrays in python numpy - python

import numpy as np
A = np.empty((0, 3))
temp = np.array([1, 1, 1])
A = np.vstack([A, temp])
A = np.vstack([A, temp])
B = [A]
temp = np.array([2, 2, 0])
A = np.vstack([A, temp])
A = np.vstack([A, temp])
A = np.vstack([A, temp])
A = np.vstack([A, temp])
B = B.append(A)
So it does not work. How do I make a list of numpy arrays? The problem is that I have N types of points. Every type of points has M number of points. Every point is 3 coordinate array. Because I dont know in the first place the values of N and M, I need to do all the things dynamicly. When I had N = 1, vstack worked perfectly, but now every type has its own M, and array is not uniform anymore. So my guess - I need to work in numpy/vstack just as if I had N = 1, but afterwards just contain this np.empty((0, 3)) arrays somewhere. Is it possible? Maybe some empty object-type dictionary?
Thank you very mush in advance!

Related

selecting random elements from each column of numpy array

I have an n row, m column numpy array, and would like to create a new k x m array by selecting k random elements from each column of the array. I wrote the following python function to do this, but would like to implement something more efficient and faster:
def sample_array_cols(MyMatrix, nelements):
vmat = []
TempMat = MyMatrix.T
for v in TempMat:
v = np.ndarray.tolist(v)
subv = random.sample(v, nelements)
vmat = vmat + [subv]
return(np.array(vmat).T)
One question is whether there's a way to loop over each column without transposing the array (and then transposing back). More importantly, is there some way to map the random sample onto each column that would be faster than having a for loop over all columns? I don't have that much experience with numpy objects, but I would guess that there should be something analogous to apply/mapply in R that would work?
One alternative is to randomly generate the indices first, and then use take_along_axis to map them to the original array:
arr = np.random.randn(1000, 5000) # arbitrary
k = 10 # arbitrary
n, m = arr.shape
idx = np.random.randint(0, n, (k, m))
new = np.take_along_axis(arr, idx, axis=0)
Output (shape):
in [215]: new.shape
out[215]: (10, 500) # (k x m)
To sample each column without replacement just like your original solution
import numpy as np
matrix = np.arange(4*3).reshape(4,3)
matrix
Output
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
k = 2
np.take_along_axis(matrix, np.random.rand(*matrix.shape).argsort(axis=0)[:k], axis=0)
Output
array([[ 9, 1, 2],
[ 3, 4, 11]])
I would
Pre-allocate the result array, and fill in columns, and
Use numpy index based indexing
def sample_array_cols(matrix, n_result):
(n,m) = matrix.shape
vmat = numpy.array([n_result, m], dtype= matrix.dtype)
for c in range(m):
random_indices = numpy.random.randint(0, n, n_result)
vmat[:,c] = matrix[random_indices, c]
return vmat
Not quite fully vectorized, but better than building up a list, and the code scans just like your description.

How to create this matrix from numpy array?

So I want to create the sparse matrix as below from the numpy array matrix as usual:
from scipy import sparse
I = np.array([0,1,2, 0,1,2, 0,1,2])
J = np.array([0,0,0,1,1,1,2,2,2])
DataElement = np.array([2,1,2,1,0,1,2,1,2])
A = sparse.coo_matrix((DataElement,(I,J)),shape=(3,3))
print(A.toarray()) ## This is what I expect to see.
My attempt with numpy is:
import numpy as np
U = np.empty((3,3,), order = "F")
U[:] = np.nan
## Initialize
U[0,0] = 2
U[2,0] = 2
U[0,2] = 2
U[2,2] = 2
for j in range(0,3):
## Slice columns first:
if (j !=0 and j!= 2):
for i in range(0,3):
## slice rows:
if (i != 0 and i != 2):
U[i,j] = 0
else:
U[i,j] = 1
One way using numpy.add.at:
arr = np.zeros((3,3), int)
np.add.at(arr, (I, J), DataElement)
print(arr)
Output:
array([[2, 1, 2],
[1, 0, 1],
[2, 1, 2]])
There are several ways of manual filling of the arrays.
First, you can explicitly define each entry:
U = np.array([[2,1,2],[1,0,1],[2,1,2]],order='F')
Or you can initialize an array with nans and then define each element by subscribing them:
U = np.empty((3,3,), order = "F")
U[:] = np.nan
U[0,0],U[0,1],U[0,2]=2,1,2
U[1,0],U[1,1],U[1,2]=1,0,1
U[2,0],U[2,1],U[2,2]=2,1,2
Finally, if there is a pattern, one can slice and define multiple values at once:
U[:,0]=[2,1,2]
U[:,1]=U[:,0]-1
U[:,2]=U[:,0]
In your attempt, you simply miss some of the entries, and they remain nans.

Concatenate many arrays in python

I have this code for concatenate two arrays.
import numpy as np
from hmmlearn import hmm
model = hmm.MultinomialHMM(n_components=3, n_iter=10,algorithm='map',tol=0.00001)
sequence3 = np.array([[2, 1, 0, 1]]).T
sequence4 = np.array([[2, 1, 0, 1, 1]]).T
sample = np.concatenate([sequence3, sequence4])
lengths = [len(sequence3), len(sequence4)]
model.fit(sample,lengths)
and it is working correctly. but now if I have more than two array. let us to say I have 10 arrays. how I can make the same process?
import numpy as np
from hmmlearn import hmm
model = hmm.MultinomialHMM(n_components=3, n_iter=10,algorithm='map',tol=0.00001)
sample = np.array([])
lengths = []
for i in range(1:10)
?????????????
model.fit(sample,lengths)
In order to concatenate more than one array, you simply concatenate the array with the concatenation of all the previous arrays.
# Create arrays
arrays=[
np.array([1,2,3]),
np.array([4,5,6]),
np.array([7,8,9])
]
# Create an array to return to
sample = np.array([])
for array in arrays:
sample = np.concatenate([sample, array])
# Print results
print('sample', sample)
print('length', len(sample))
You can use vstack
That is,
Equivalent to np.concatenate(tup, axis=0) if tup contains arrays that
are at least 2-dimensional.
store your arrays as a list,say array_list
print np.vstack(array_list)
Sample:
import numpy as np
sequence3 = np.array([[2, 1]]).T
sequence4 = np.array([[2, 5]]).T
sequence5 = np.array([[4, 5]]).T
sequence6 = np.array([[6, 7]]).T
array_list=[sequence3,sequence4,sequence5,sequence6]
sample = np.concatenate([sequence3, sequence4])
lengths = [len(sequence3), len(sequence4)]
print np.vstack(array_list)
[[2]
[1]
[2]
[5]
[4]
[5]
[6]
[7]]
Hope it helps!

Python NumPy: How to fill a matrix using an equation

I wish to initialise a matrix A, using the equation A_i,j = f(i,j) for some f (It's not important what this is).
How can I do so concisely avoiding a situation where I have two for loops?
numpy.fromfunction fits the bill here.
Example from doc:
>>> import numpy as np
>>> np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
One could also get the indexes of your array with numpy.indices and then apply the function f in a vectorized fashion,
import numpy as np
shape = 1000, 1000
Xi, Yj = np.indices(shape)
A = (2*Xi + 3*Yj).astype(np.int) # or any other function f(Xi, Yj)

multiplication of 3-dimensional matrix in numpy

I think I asked the wrong question yesterday. What I actually want is to mutiply two 2x2xN matrices A and B, so that
C[:,:,i] = dot(A[:,:,i], B[:,:,i])
For example, if I have a matrix
A = np.arange(12).reshape(2, 2, 3)
How can I get C = A x A with the definition described above? Is there a built-in function to do this?
Also, if I multiply A (shape 2x2xN) with B (shape 2x2x1, instead of N), I want to get
C[:,:,i] = dot(A[:,:,i], B[:,:,1])
Try using numpy.einsum, it has a little bit of a learning curve but it should give you what you want. Here is an example to get you started.
import numpy as np
A = np.random.random((2, 2, 3))
B = np.random.random((2, 2, 3))
C1 = np.empty((2, 2, 3))
for i in range(3):
C1[:, :, i] = np.dot(A[:, :, i], B[:, :, i])
C2 = np.einsum('ijn,jkn->ikn', A, B)
np.allclose(C1, C2)

Categories