Related
This question already has answers here:
Numpy extract submatrix
(6 answers)
How to create a sub-matrix in numpy
(2 answers)
Closed 2 years ago.
I'm relatively new to Python and would appreciate your help!
Suppose I have two square matrices - one large M and one smaller K - and an integer array of indices ind, not necessarily sorted. The length of ind matches the dimensions of K. In Octave/MATLAB, I can easily do this:
M(ind, ind) = K
This will distribute all the components of K to those positions of M that correspond to indices ind. This is often used in Finite Element computations.
Is there a way to do the same thing just as elegantly in Python? You may assume my M and K are NumPy arrays that were constructed via the operations:
M = np.zeros((12, 12))
K = np.zeros((6, 6))
I did some work on these matrices and filled them with data. My ind array is a NumPy array as well.
However, when I do something like
M[ind, ind] = K
I get shape mismatch as an error. Plugging ind.tolist() instead of ind into M won't change anything.
Thanks for any advice!
You are looking for this:
M[np.ix_(ind,ind)] = K
example:
M = np.zeros((12, 12))
K = np.ones((6, 6))
ind = np.arange(6)
output:
[[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
If you are using numpy arrays, It can be donde directly using this syntax:
import numpy as np
M = np.zeros((12, 12))
K = np.ones((6, 6))
M[:6, :6] = K
# This is equivalent to:
# M[0:6, 0:6] = K
M will then look like this:
array([[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
Here you have more information about slice indexing in python
https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/
I have a program that generating 2D arrays with different number of rows and appending them to list. I need to combine that list into one 3D array of 2D arrays.
A = np.zeros(15).reshape(3,5)
B = np.zeros(20).reshape(4,5)
C = np.zeros(25).reshape(5,5)
lst = [A, B, C]
[array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]]),
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]]),
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])]
Needs 3D array that looks like this
[[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]]
Use the tolist method:
lst = [A.tolist(), B.tolist(), C.tolist()]
Or more generic:
lst_of_arrays = [A, B, C] # Could be initialized differently
lst = [ar.tolist() for ar in lst_of_arrays ]
I'm having problem with this code. I think I'm doing something wrong.
import numpy as np
array = np.zeros(10)
arrays = []
for i in range(len(array)):
array[i] = 1
arrays.append(array)
print(arrays[0])
I was expecting to get:[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
But I'm getting:[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
That is the last array I appended to arrays, and not the first one. Why is that happening and more important what can I do to get the desired output?
I think you are expecting:
arrays.append(array)
to add a COPY of your main array to the arrays list. But that's not what you're doing. You're pushing another reference to the same array each time you do:
arrays.append(array)
so at the end of your loop, you have the list arrays with 10 references to the same original array you created. By then, you've set every value of that ONE ARRAY to 1. So you get that the first value in arrays contains an array with every value set to 1 because every array in arrays is that same array.
If you actually copy a new array each time into arrays, I bet you'll get what you expected. To do that, change that line to:
arrays.append(array.copy())
Here's a complete version of your program with this fix. I changed it also to print all 10 of the arrays in arrays:
def main():
import numpy as np
array = np.zeros(10)
arrays = []
for i in range(len(array)):
array[i] = 1
arrays.append(array.copy())
for array in arrays:
print(array)
Result:
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
just add this change:
arrays.append(np.array(array))
The actual way to do this in numpy is with np.tri():
np.tri(10)
Out[]:
array([[ 1., 0., 0., ..., 0., 0., 0.],
[ 1., 1., 0., ..., 0., 0., 0.],
[ 1., 1., 1., ..., 0., 0., 0.],
...,
[ 1., 1., 1., ..., 1., 0., 0.],
[ 1., 1., 1., ..., 1., 1., 0.],
[ 1., 1., 1., ..., 1., 1., 1.]])
Maybe you are looking for this , just added if condition in your code
import numpy as np
array = np.zeros(10)
arrays = []
for i in range(len(array)):
if i==0:
array[i] = 1
arrays.append(array)
print(arrays[0])
out: [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
You can use array.copy() a method defined on numpy arrays as #Steve has suggested.
As it has been already used in one of the answer (#Steve's answer) to this problem so I choose another approach i.e. deepcopy() functionto obtain the result.
import numpy as np
from copy import deepcopy
array = np.zeros(10)
arrays = []
for i in range(len(array)):
array[i] = 1
arrays.append(deepcopy(array))
print(arrays)
# [array([1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), array([1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]), array([1., 1., 1., 0., 0., 0., 0., 0., 0., 0.]), array([1., 1., 1., 1., 0., 0., 0., 0., 0., 0.]), array([1., 1., 1., 1., 1., 0., 0., 0., 0., 0.]), array([1., 1., 1., 1., 1., 1., 0., 0., 0., 0.]), array([1., 1., 1., 1., 1., 1., 1., 0., 0., 0.]), array([1., 1., 1., 1., 1., 1., 1., 1., 0., 0.]), array([1., 1., 1., 1., 1., 1., 1., 1., 1., 0.]), array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])]
print(arrays[0])
# [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
print(arrays[-1])
# [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
My end goal is to train a 4D multivariate gaussian distribution parameterized on the mean and covariance
where,
and,
Currently I have the following code:
import tensorflow as tf
import numpy as np
value = [[1,2.0,3,4,5],[0,2,4,6,8],[80,7,6,5,4]]
value=tf.constant(value)
cov= tf.slice(value,[0,int(value.shape[1])-1],[int(value.shape[0]),1])
mean= tf.slice(value,[0,0],[int(value.shape[0]),int(value.shape[1])-1])
eyes=tf.eye(int(mean.shape[1]),batch_shape=[int(value.shape[0])])
#eyes = tf.multiply(eyes,cov)
normal = tf.contrib.distributions.MultivariateNormalFullCovariance(
loc=mean,
covariance_matrix=eyes)
value = [[1,2.0,3,4,5],[0,2,4,6,8],[80,7,6,5,4]] is an example of what the rest of the code may be receiving.
In the example above
cov = <tf.Tensor 'Slice_2:0' shape=(3, 1) dtype=float32>
eyes = <tf.Tensor 'eye_1/MatrixDiag:0' shape=(3, 4, 4) dtype=float32>
cov = [[5.] [8.] [4.]]`
eyes = [[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]]`
My question is, How can I obtain result given cov and eyes? where result is as follows:
result = [[[5., 0., 0., 0.],
[0., 5., 0., 0.],
[0., 0., 5., 0.],
[0., 0., 0., 5.]],
[[8., 0., 0., 0.],
[0., 8., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 8.]],
[[4., 0., 0., 0.],
[0., 4., 0., 0.],
[0., 0., 4., 0.],
[0., 0., 0., 4.]]]
Thanks, in advance.
Tensorflow uses the same type of indexing as numpy, which can be quite powerful.
You can look at details here: https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html Note that np.newaxis is defined to be the same as None.
For your problem, you can add an extra dimension to your data to make sure there's no ambiguity in how arrays get multiplied.
import numpy as np
cov = np.array([[5.],[8.],[4.]])
eyes = np.array([[[1.0,0,0,0],[0.0,1.0,0.0,0],[0.0,0.0,1.0,0],[0.0,0.0,0.0,1.0]],[[1.0,0,0,0],[0.0,1.0,0.0,0],[0.0,0.0,1.0,0],[0.0,0.0,0.0,1.0]],[[1.0,0,0,0],[0.0,1.0,0.0,0],[0.0,0.0,1.0,0],[0.0,0.0,0.0,1.0]]])
result = cov[:,:,None]*eyes
Using None here adds an extra dimension, making cov into a 3x1x1 array, which can unambiguously multiply with a 3x4x4 array. You can use None this way in tensorflow as well.
Two arrays can multiply unambiguously if each corresponding dimensions are either the same size, or one of them has size 1.
This might be a super easy question if you know how to do it, but I just can't figure out the syntax:
I have an array of 5x10 zeros: y1 = np.zeros((5,10)) and an array 5x1 of index: index=np.array([2,3,2,5,6]). For each row of y1, I would like to set 1 at the column given by the index. The result would look like
array([[ 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.]])
Anyone can help please :-) ?
You can do multi-dimensional array indexing with array[index_1, index_2]. For your problem:
y1[range(y1.shape[0]), index] = 1
range(y1.shape[0]) generates the array [0,1,...,n-1], where n is the number of rows in y1. This array is your row index, and index is your column index.
Just use an enumerate()
import numpy as np
y1 = np.zeros((5,10))
index=np.array([2,3,2,5,6])
for i,item in enumerate(y1):
item[index[i]] = 1
print(y1)
# [[ 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
# [ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
# [ 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
# [ 0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
# [ 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]]
Does this do what you want?