how to access a matrix and increase specific column? - python

For example, I have this matrix, and I need to access the second column and increase it by 2:
m = [[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]

You can do that just by accessing the 2nd column and incrementing the value. You can do that by doing this : m[:, 1] = m[:, 1] + 2
It means that you are ignoring all the rows and specifying the columns. Here, 1 refers to the 2nd column.
You can do this by using numpy library which allows you to easily do such thing.
Import numpy as import numpy as np
Convert the 2d list into numpy array
m = np.array([
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]
])
Now apply the conditioning
m[:, 1] = m[:, 1] + 2
Print the output.
print("M: ", m)
Combined Code:
import numpy as np
m = np.array([
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]
])
m[:, 1] = m[:, 1] + 2
print("M: ", m)

So, you need to increase the second element of each row by 2. You could achieve this by a for loop.
for row in m:
row[1] += 2

You could convert the matrix into a numpy array. Just in case you're looking at exploiting the optimisations that this library offers
import numpy as np
m = np.array([
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]
])
m[:, 1] += 1

Related

Python: Fill out edges of binary array

I'm using the following code to generate an array based on coordinates of edges:
verts = np.array(list(itertools.product((0,2), (0,2))))
arr = np.zeros((5, 5))
arr[tuple(verts.T)] = 1
plt.imshow(arr)
which gives me
or, as a numeric array:
[[1., 0., 1., 0., 0.],
[0., 0., 0., 0., 0.],
[1., 0., 1., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]]
Now, I would like to fill out the spaces in between the corners (ie. yellow squares):
so that I get the following array:
[[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.]]
Replace (0,2) using range(0,3) (3 as ranges are inclusive-exclusive) that is
import itertools
import numpy as np
verts = np.array(list(itertools.product(range(0,3), range(0,3))))
arr = np.zeros((5, 5))
arr[tuple(verts.T)] = 1
print(arr)
output
[[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.]]

tf.keras.utils.to_categorical mixing classes

I am using tf.keras.utils.to_categorical() for data preparation.
I have this very simple list and I want to get the categorical values out of it.
So I do this:
tf.keras.utils.to_categorical([1,2,3], num_classes=6)
and I get:
array([[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.]], dtype=float32)
Now for further usage, I reduce the values I sent to the function by 1, to get a amount of 6 classes, without 0 as placeholder:
tf.keras.utils.to_categorical([x -1 for x in [1,2,3]], num_classes=6)
which results in this:
array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.]], dtype=float32)
Now comes the weird part. I want to set certain features to 0 and thats why I found this behaviour:
tf.keras.utils.to_categorical([x -1 for x in [-4,2,3]], num_classes=6)
results in:
array([[0., 1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.]], dtype=float32)
So to_categorical() is mixing -4 and 2 into the same class, which I find pretty weird. I would have expected an exception as the list was not map-able to 6 classes. But I did not expect this to happen. Is this a bug or a feature, why is this happening?
Thanks!
That's completely normal. It just works consistently with Python's negative indexing. See:
import tensorflow as tf
tf.keras.utils.to_categorical([0, 1, 2, -1, -2, -3])
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 1.],
[0., 1., 0.],
[1., 0., 0.]], dtype=float32)
To put it differently:
import tensorflow as tf
a = tf.keras.utils.to_categorical([0, 1, 2], num_classes=3)
b = tf.keras.utils.to_categorical([-3, -2, -1], num_classes=3)
print(a)
print(b)
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
If you want to know why this happened, I think to_categorical in keras doesn't work with negative numbers. but if you want to solve it I suggest to make all numbers greater than 0.
this code do that:
arr=numpy.array([-5,-4,-2,-1,0,1,2,3,4]) #anything
arr+=(0-arr.min())
Keras to_categorical doesn't work for negative numbers. It's clearly written that the numbers must start from 0.
https://keras.io/api/utils/python_utils/#to_categorical-function
If you still need to make it work, make a dictionary to map the negative numbers.

Update a matrix through advanced indexing/vectorizing

I have a matrix of what is effectively counters. I would like to increment those counters based on a list of column indices - with each positional index also corresponding to a row increment.
This is straightforward with a for loop, and a little less straightforward with list comprehension. In either case, iteration is involved. But I was wondering if there is any way to vectorise this problem?
The minimal problem is:
counters = np.zeros((4,4))
counters
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
update_columns = [1,0,2,2]
for row, col in zip(range(len(update_columns)), update_columns):
counters[row, col] += 1
counters
array([[0., 1., 0., 0.],
[1., 0., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 1., 0.]])
What you are looking for is called advanced numpy indexing. You can pass the row index using np.arange and column index using update_columns:
update_columns = np.array(update_columns)
counters[np.arange(update_columns.size), update_columns] += 1
output:
[[0. 1. 0. 0.]
[1. 0. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 1. 0.]]

Vectorizing creation of array of diagonal matrix, [duplicate]

This question already has answers here:
Vectorized creation of an array of diagonal square arrays from a liner array in Numpy or Tensorflow
(5 answers)
Closed 3 years ago.
I have a 2d array called diagonals where each row represents the diagonal of a 2d matrix. What's the fastest/best way to create a 3d array diag_matricies where the last two dimensions each consist of a diagonal matrix created using the rows of diagonals?
In a loop this is what I want:
import numpy as np
diag_matricies = np.zeros([3,3,3])
diagonals = np.array([[1,2,3],[4,5,6],[7,8,9]])
for i in range(3):
diag_matricies[i] = np.diag(diagonals[i,:])
print(diag_matricies)
One faster alternative is to use advanced indexing:
index = np.arange(3)
diag_matricies[:, index, index] = diagonals
[[[1. 0. 0.]
[0. 2. 0.]
[0. 0. 3.]]
[[4. 0. 0.]
[0. 5. 0.]
[0. 0. 6.]]
[[7. 0. 0.]
[0. 8. 0.]
[0. 0. 9.]]]
Timing with the size of each dimension being 1200:
from datetime import datetime
N = 1200
diag_matricies = np.zeros([N, N, N])
diagonals = np.arange(N * N).reshape((N, N))
start = datetime.now()
index = np.arange(N)
diag_matricies[:, index, index] = diagonals
print('advanced indexing: ', datetime.now() - start)
start = datetime.now()
for i in range(N):
diag_matricies[i] = np.diag(diagonals[i])
print('for loop: ', datetime.now() - start)
# advanced indexing: 0:00:01.537120
# for loop: 0:00:07.281833
You can use np.einsum:
>>> out = np.zeros((3,3,3))
>>> np.einsum('ijj->ij',out)[...] = diagonals
>>> out
array([[[1., 0., 0.],
[0., 2., 0.],
[0., 0., 3.]],
[[4., 0., 0.],
[0., 5., 0.],
[0., 0., 6.]],
[[7., 0., 0.],
[0., 8., 0.],
[0., 0., 9.]]])
What this does under the hood is more or less the following:
>>> out2 = np.zeros((3,3,3))
>>> out2.reshape(3,9)[:,::4] = diagonals
>>> out2
array([[[1., 0., 0.],
[0., 2., 0.],
[0., 0., 3.]],
[[4., 0., 0.],
[0., 5., 0.],
[0., 0., 6.]],
[[7., 0., 0.],
[0., 8., 0.],
[0., 0., 9.]]])
only the einsum method also works for noncontiguous arrays.

How to convert a binary matrix to a bipolar one in python

There is a function in Keras to generate a binary matrix for an array of labels:
# Consider an array of 5 labels out of a set of 3 classes {0, 1, 2}:
> labels
array([0, 2, 1, 2, 0])
# `to_categorical` converts this into a matrix with as many
# columns as there are classes. The number of rows
# stays the same.
> to_categorical(labels)
array([[ 1., 0., 0.],
[ 0., 0., 1.],
[ 0., 1., 0.],
[ 0., 0., 1.],
[ 1., 0., 0.]], dtype=float32)
I need the above functionality, but having -1 instead of zeros. I didn't find any option or other functions to do it. Is there any easy way to do that?
You could do the following:
import numpy as np
arr = np.array([[1., 0., 0.],
[0., 0., 1.],
[0., 1., 0.],
[0., 0., 1.],
[1., 0., 0.]])
arr[np.isclose(arr, 0)] = -1
print(arr)
Output
[[ 1. -1. -1.]
[-1. -1. 1.]
[-1. 1. -1.]
[-1. -1. 1.]
[ 1. -1. -1.]]
Just rescale your data:
2*to_categorical(labels)-1

Categories