How do I make append work as intended with arrays? - python

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.]

Related

Identity matrix of 3 Dimensional matrix

Identity = array([[[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.]]])
There is a task which wants me to create identity matrix in 3D.
I have made assumptions that the above is the identity matrix in 3D with the shape (3,4,4).
I have seen other variations of identity of 3D matrix which I didn't understand. Check this What's the best way to create a "3D identity matrix" in Numpy? for reference.
If I am right in my above assumption of identity matrix. Please assist me to construct the same with numpy.
You can use np.identity() to generate an identity matrix and then use np.broadcast_to() to add the third dimension:
import numpy as np
n = 4
print(np.broadcast_to(np.identity(n), (3, n, n)))
You can also use np.tile:
n = 4
k = 3
out = np.tile(np.identity(n), (k,1)).reshape(k,n,n)
Output:
[[[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.]]]

Is there a NumPy method to change a range of values in a 2d array?

I would like to change a range of values in a 2d NumPy array in a simple way. For example, imagine I have a 2d array of shape (5,5). If I want to change the values of the upper 2x2 'block', I can use the NumPy put function. This is an example:
import numpy as np
A = np.zeros(shape=(5,5))
np.put(A, [[0,1,2,5,6,7,10,11,12]], 1)
Resulting in:
print(A)
[[1. 1. 1. 0. 0.]
[1. 1. 1. 0. 0.]
[1. 1. 1. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
Ideally, however, I would like to do the following: use the coordinates of a square to directly change a range of values, without flattening the array. In the example, these coordinates would be [(0,0), (2,2)]. Is there a Pythonic way of doing this?
IIUC, you can try:
cor = [(1,1), (2,2)]
(x1,y1),(x2,y2) = cor
a[x1:x2+1, y1:y2+1] =1
OUTPUT:
array([[0., 0., 0., 0., 0.],
[0., 1., 1., 0., 0.],
[0., 1., 1., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])

Accessing matrix in Python by an array of indices [duplicate]

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/

List of 2D arrays with different size into 3D array

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 ]

Python indirect indexing

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?

Categories