How to convert diameter of matrix to zero in python? - python

I have a matrix and I want to convert diameter value to zero in python. can you help me?
Matrix:
array([[1, 0, 0, ..., 1, 0, 0],
[0, 1, 0, ..., 0, 0, 0],
[0, 0, 1, ..., 0, 0, 0],
...,
[1, 0, 0, ..., 1, 0, 0],
[0, 0, 0, ..., 0, 1, 0],
[0, 0, 0, ..., 0, 0, 1]])

assuming you meant diagonal, iterate over the list with enumerate, then iterate over the sublist, and check if the indexes are equal (that means you're on the diagonal), and assign zero, else the current value.
mydata = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
for i,l in enumerate(mydata):
l[i]=0
[0, 2, 3, 4]
[5, 0, 7, 8]
[9, 10, 0, 12]
[13, 14, 15, 0]

When possible, avoid nested loops.
As you are working with numpy's arrays, you can use
np.fill_diagonal(mydata, 0)

Related

How to count non zero rows in a N-d tensor?

I need to find the number of non zero rows and put them in a 1D tensor(kind of vector).
For an example:
tensor = [
[
[1, 2, 3, 4, 0, 0, 0],
[4, 5, 6, 7, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
],
[
[4, 3, 2, 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],
[4, 5, 6, 7, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
]
]
the tensor shape will be [None,45,7] in a real application, but here it is [3,2,7].
So I need to find the number of non-zero rows in dimension 1 and keep them in a 1d tensor.
non_zeros = [2,1,1] #result for the above tensor
I need to do it in TensorFlow, if it is in NumPy, I would have done it.
Can anyone help me with this?
Thanks in advance
You can use tf.math.count_nonzero combined with tf.reduce_sum
>>> tf.math.count_nonzero(tf.reduce_sum(tensor,axis=2),axis=1)
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([2, 1, 1])>
Try this code:
t = tf.math.not_equal(tensor, 0)
t = tf.reduce_any(t, -1)
t = tf.cast(t, tf.int32)
t = tf.reduce_sum(t, -1)

Is there any way to compute the Hadamard product of COO sparse matrices leveraging its structure?

I am trying to compute the Hadamard product of two matrices stored in COO-sparse format (in SciPy). There's a lecture that reads
fast and easy item-wise operations, manipulate data array directly (fast NumPy machinery)
I understand the sum and difference part since we can just concatenate the matrix.row, matrix.column and matrix.data. However, I guess it's actually quite non-trivial to compute the Hadamard/entry-wise product by leveraging the COO structure (possibly have to match the coordinates and apply "&").
Is there any way to compute Hadamard product more efficiently using COO-sparse format or is it just a misunderstanding?
The multiply method does element-wise multiplication.
Here's an example, in which a and b are sparse matrices with COO format. (The .A attribute returns a regular numpy array. I use it to display the values in the sparse matrices.)
In [41]: a
Out[41]:
<5x8 sparse matrix of type '<class 'numpy.int64'>'
with 20 stored elements in COOrdinate format>
In [42]: a.A
Out[42]:
array([[0, 9, 2, 9, 0, 6, 6, 2],
[2, 0, 0, 0, 1, 0, 8, 0],
[0, 3, 0, 0, 2, 9, 0, 4],
[0, 0, 0, 0, 0, 0, 0, 5],
[0, 0, 7, 1, 0, 0, 7, 7]])
In [43]: b
Out[43]:
<5x8 sparse matrix of type '<class 'numpy.int64'>'
with 20 stored elements in COOrdinate format>
In [44]: b.A
Out[44]:
array([[0, 0, 0, 7, 9, 0, 5, 0],
[0, 7, 0, 0, 6, 6, 0, 0],
[3, 0, 2, 0, 3, 0, 0, 0],
[5, 0, 0, 3, 0, 0, 7, 0],
[8, 0, 6, 8, 0, 0, 4, 0]])
Compute the element-wise product of a and b. Note that c uses the CSR format.
In [45]: c = a.multiply(b)
In [46]: c
Out[46]:
<5x8 sparse matrix of type '<class 'numpy.int64'>'
with 7 stored elements in Compressed Sparse Row format>
In [47]: c.A
Out[47]:
array([[ 0, 0, 0, 63, 0, 0, 30, 0],
[ 0, 0, 0, 0, 6, 0, 0, 0],
[ 0, 0, 0, 0, 6, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 42, 8, 0, 0, 28, 0]], dtype=int64)
Verify the result by computing the element-wise product of the corresponding numpy arrays.
In [48]: a.A * b.A
Out[48]:
array([[ 0, 0, 0, 63, 0, 0, 30, 0],
[ 0, 0, 0, 0, 6, 0, 0, 0],
[ 0, 0, 0, 0, 6, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 42, 8, 0, 0, 28, 0]])

Modify every two largest elements of matrix rows and columns

In python, I have a matrix and I want to find the two largest elements in every row and every column and change their values to 1 (seperately, I mean get two matrices where one of them modified the rows and the other modified the cols).
The main goal is to get a corresponding matrix with zeros everywhere except those ones I've put in the 2 largest element of each row and column (using np.where(mat == 1, 1, 0).
I'm trying to use the np.argpartition in order to do so but without success.
Please help.
See image below.
Here's an approach with np.argpartition -
idx_row = np.argpartition(-a,2,axis=1)[:,:2]
out_row = np.zeros(a.shape,dtype=int)
out_row[np.arange(idx_row.shape[0])[:,None],idx_row] = 1
idx_col = np.argpartition(-a,2,axis=0)[:2]
out_col = np.zeros(a.shape,dtype=int)
out_col[idx_col,np.arange(idx_col.shape[1])] = 1
Sample input, output -
In [40]: a
Out[40]:
array([[ 3, 7, 1, -5, 14, 2, 8],
[ 5, 8, 1, 4, -3, 3, 10],
[11, 3, 5, 1, 9, 2, 5],
[ 6, 4, 12, 6, 1, 15, 4],
[ 8, 2, 0, 1, -2, 3, 5]])
In [41]: out_row
Out[41]:
array([[0, 0, 0, 0, 1, 0, 1],
[0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 1]])
In [42]: out_col
Out[42]:
array([[0, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 1, 1],
[1, 0, 1, 0, 1, 0, 0],
[0, 0, 1, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0]])
Alternatively, if you are into compact codes, we can skip the initialization and use broadcasting to get the outputs from idx_row and idx_col directly, like so -
out_row = (idx_row[...,None] == np.arange(a.shape[1])).any(1).astype(int)
out_col = (idx_col[...,None] == np.arange(a.shape[0])).any(0).astype(int).T

How to look at only the 3rd value in all lists in a list

I have a list of lists and I want to be able to refer to the 1st, 2nd, 3rd, etc. column in a list of lists. Here is my code for the list:
matrix = [
[0, 0, 0, 5, 0, 0, 0, 0, 6],
[8, 0, 0, 0, 4, 7, 5, 0, 3],
[0, 5, 0, 0, 0, 3, 0, 0, 0],
[0, 7, 0, 8, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[9, 0, 0, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 9, 0, 0, 0, 1, 0],
[7, 0, 8, 3, 2, 0, 0, 0, 5],
[3, 0, 0, 0, 0, 8, 0, 0, 0],
]
I want to be able to say something like:
matrix = [
[0, 0, 0, 5, 0, 0, 0, 0, 6],
[8, 0, 0, 0, 4, 7, 5, 0, 3],
[0, 5, 0, 0, 0, 3, 0, 0, 0],
[0, 7, 0, 8, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[9, 0, 0, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 9, 0, 0, 0, 1, 0],
[7, 0, 8, 3, 2, 0, 0, 0, 5],
[3, 0, 0, 0, 0, 8, 0, 0, 0],
]
if (The fourth column in this matrix does not have any 1's in it):
(then do something)
I want to know what the python syntax would be for the stuff in parenthesis.
The standard way to perform what you asked is to do a list comprehension
if (The fourth column in this matrix does not have any 1's in it):
translates in:
>>>if not any([1 == row[3] for row in matrix])
However, depending on how often you need to perform this operation, how big is your matrix, etc... you might wish to look into numpy as it is easier (and remarkably faster) to address columns. An example:
>>> import numpy as np
>>> matrix = np.random.randint(0, 10, (5, 5))
>>> matrix
array([[3, 0, 9, 9, 3],
[5, 7, 7, 7, 6],
[5, 4, 6, 2, 2],
[1, 3, 5, 0, 5],
[3, 9, 7, 8, 6]])
>>> matrix[..., 3] #fourth column
array([9, 7, 2, 0, 8])
Try this:
if all(row[3] != 1 for row in matrix):
# do something
The row[3] part takes a look at the fourth element of a row, the for row in matrix part looks at all the rows in the matrix - this produces a list with all the fourth elements in all the rows, that is, the whole fourth column. Now if it is true for all the elements in the fourth column that they're different from one, then the condition is satisfied and you can do what you need inside the if.
A more traditional approach would be:
found_one = False
for i in xrange(len(matrix)):
if matrix[i][3] == 1:
found_one = True
break
if found_one:
# do something
Here I'm iterating over all the rows (i index) of the fourth column (3 index), and checking if an element is equal to one: if matrix[i][3] == 1:. Notice that the for cycle goes from the 0 index up to the "height" of the matrix minus one, that's what the xrange(len(matrix)) part says.
if 1 in [row[3] for row in matrix]:

How do I add a guard ring to a matrix in NumPy?

Using NumPy, a matrix A has n rows and m columns, and I want add a guard ring to matrix A. That guard ring is all zero.
What should I do? Use Reshape? But the element is not enough to make a n+1 m+1 matrix.
Or etc.?
Thanks in advance
I mean an extra ring of cells that always contain 0 surround matrix A.Basically there is a Matrix B has n+2rows m+2columns where the first row and columns and the last row and columns are all zero,and the rest of it are same as matrix A.
Following up on your comment:
>>> import numpy
>>> a = numpy.array(range(9)).reshape((3,3))
>>> b = numpy.zeros(tuple(s+2 for s in a.shape), a.dtype)
>>> b[tuple(slice(1,-1) for s in a.shape)] = a
>>> b
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])
This is a less general but easier to understand version of Alex's answer:
>>> a = numpy.array(range(9)).reshape((3,3))
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> b = numpy.zeros(a.shape + numpy.array(2), a.dtype)
>>> b
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]])
>>> b[1:-1,1:-1] = a
>>> b
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])
This question is ancient now, but I just want to alert people finding it that numpy has a function pad that very easily accomplishes this now.
import numpy as np
a = np.array(range(9)).reshape((3, 3))
a
Out[15]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
a = np.pad(a, pad_width=((1,1),(1,1)), mode='constant', constant_values=0)
a
Out[16]:
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])

Categories