How do I create many matrices inside a loop statement with python? - python

I want to create for example n matrices like:
m1 = [[0,0],[0,0]]
m2 = [[0,0],[0,0]]
.
.
mn = [[0,0],[0,0]]

I think that will work for you
res = [[[0 for item3 in range(2)] for item2 in range(2)] for item1 in range(10)]
print res
Output:
[
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]],
[[0, 0], [0, 0]]
]
Basically 10(your n value) arrays with 2x2 lists of zeros.

Related

List of lists with incremented elements

I've made some generic example of my problem.
I have something like this:
n = 2
test = [[[0,0] for j in range(1)] for k in range(n)]
print(test)
And I get the following output:
[[[0, 0]], [[0, 0]]]
But what I want - as output - is something like that:
[[[0, 0]], [[0, 0],[0, 0]]]
And for n = 3, the output must be:
[[[0, 0]], [[0, 0],[0, 0]], [[0,0],[0,0],[0,0]]]
You can do it by specifying the start argument of range:
[[[0,0] for _ in range(k)] for k in range(1, n+1)]
Output (for n=3):
[[[0, 0]], [[0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]

How to change a specific element in a matrix to match another matrix?

I am writing a program that involves me to create a matrix 'B' edited from another matrix 'A'. Both the matrix have the same size and I simply want that for every position where matrix 'A' contains a 1, matrix 'B' also contains a 1 in that position. For example:
if __name__ == '__main__':
mat_A = [[0, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 0, 0]]
R = len(mat_A)
C = len(mat_A[1])
mat_B = [[0]*C]*R #Initialise matrix B to be the same size as A
for i in range (R):
for j in range (C):
if mat_A[i][j] == 1:
mat_B[i][j] = 1
print(mat_B)
However, in this case, it prints me an output like such:
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
Process finished with exit code 0
This tells me that the code is finding an instance where mat_A[i][j] = 1 and then changing the entire mat_B together. Shouldn't it only affect the specific position in 'B' rather than all?
Thank you for your help.
p.s. The above is only a very simple example I wrote to try and debug. There are multiple complex steps in the if loop.
The line
mat_B = [[0]*C]*R
creates a list of length R where each element is the same list consisting of zeros. If you change one of the sublists of mat_B, you change them all, since they are all the same list. You can fix this, for example, as follows:
mat_B = [[0]*C for i in range(R)]
After that, your code should work fine.
As a side note, it is easier to accomplish such operations using numpy arrays:
import numpy as np
mat_A = np.array([[1, 2, 3], [0, 1, 7], [3, 1, 0], [0, 1, 0], [0, 2, 4]])
mat_B = np.zeros_like(mat_A)
mat_B[mat_A == 1] = 1

Numpy Use 2D array as heightmap-like index for 3D array

I want to use a 2D array as an index for a 3D array as a heightmap to index axis 0 of the 3D array. Is there an efficient "numpy-way" of doing this? In my example I want to set everything at equal or greater height of the heightmap in each corresponding pillar two zero. Example:
3D Array:
[[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]]
2D Array (heightmap):
[[0, 1, 2],
[2, 3, 4],
[2, 0, 0]]
Desired output:
[[[0, 1, 1],
[1, 1, 1],
[1, 0, 0]],
[[0, 0, 1],
[1, 1, 1],
[1, 0, 0]],
[[0, 0, 0],
[0, 1, 1],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 1],
[0, 0, 0]]]
So far I have implemented this with a for python loop as in
for y in range(arr2d.shape[0]):
for x in range(arr2d.shape[1]):
height = arr2d[y, x]
arr3d[height:, y, x] = 0
but this seems very ineffecient and I feel like there might be a way better way to do this.
Drawing inspiration from an fast way of padding arrays:
In [104]: (np.arange(4)[:,None,None]<arr2d).astype(int)
Out[104]:
array([[[0, 1, 1],
[1, 1, 1],
[1, 0, 0]],
[[0, 0, 1],
[1, 1, 1],
[1, 0, 0]],
[[0, 0, 0],
[0, 1, 1],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 1],
[0, 0, 0]]])

Unexpected behaviour in list value change

I defined this function:
def newMap(dim, n):
tc = [0 for i in range(n)]
return [[tc for _ in range(dim)] for _ in range(dim)]
Which creates a list of lists of zeroes. For example
m = newMap(2,2)
print(m)
returns
[[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
I want to change one os the zeroes to obtain [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] and tried doing so by
m[0][0][0] = 1
which, unexpectedly returns [[[1, 0], [1, 0]], [[1, 0], [1, 0]]] instead of [[[1, 0], [0, 0]], [[0, 0], [0, 0]]].
However, if I defined a = [[[0, 0], [0, 0]], [[0, 0], [0, 0]]], and then do
a[0][0][0] = 1
print(a)
it returns [[[1, 0], [0, 0]], [[0, 0], [0, 0]]], which is what I want.
Why does this happen? Shouldn't the two definitions be equivalent? How can I prevent it from happening in the first case?
Use tc.copy() this should fix it, i tried it and it works:
def newMap(dim, n):
tc = [0 for i in range(n)]
return [[tc.copy() for _ in range(dim)] for _ in range(dim)]
a = newMap(2,2)
a
#[[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
a[0][0][0] = 1
#[[[1, 0], [0, 0]], [[0, 0], [0, 0]]]

Generate one-hot vector from a nx1 array of binary labels

I have an array like this:
X = [0,0,1,1,0,0,1,1,1,0,0,0]
I want to create a one-hot encoder vector of nx2
one_hotX = [[1,0],[1,0],[0,1],[0,1],[1,0]...]
Is there an easy way to do this? OneHotEncoder and LabelEncoder don't seem to work.
How about constructing the vector by yourself:
[[0, 1] if i else [1, 0] for i in X]
#[[1, 0],
# [1, 0],
# [0, 1],
# [0, 1],
# [1, 0],
# [1, 0],
# [0, 1],
# [0, 1],
# [0, 1],
# [1, 0],
# [1, 0],
# [1, 0]]
If you are working with numpy, you could do something such as this as well(vectorized approach):
import numpy as np
code = np.array([[1,0],[0,1]])
arrX = np.array(X)
code[arrX]
#array([[1, 0],
# [1, 0],
# [0, 1],
# [0, 1],
# [1, 0],
# [1, 0],
# [0, 1],
# [0, 1],
# [0, 1],
# [1, 0],
# [1, 0],
# [1, 0]])

Categories