Identifying ones in each row and creating a list in Python

Question:

I have an array A. I am identifying ones in each row except the row number itself and creating a list. For example, in A[0], the ones should be identified for locations 2,3,5 and not 0. I present the current and expected output.

import numpy as np

A=np.array([[1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
       [1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
       [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0],
       [0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1],
       [0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1],
       [0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0],
       [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1]])

output = []
for i, row in enumerate(A):
    ones_indices = np.where(row == 1)[0]
    other_rows = np.arange(A.shape[0])
    other_rows = np.delete(other_rows, i)
    output.append([[i], other_rows.tolist()])

print(output)

The current output is

[[[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]], [[1], [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]], [[2], [0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11]], [[3], [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11]], [[4], [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11]], [[5], [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11]], [[6], [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11]], [[7], [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11]], [[8], [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11]], [[9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11]], [[10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]], [[11], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]

The expected output is

[[[0], [2,3,5]], [[1], [3,4,6]], [[2], [0,3,5]], [[3], [0, 1, 2, 4, 5, 6]], [[4], [1,3,6]], [[5], [0,2,3,7,8,10]], [[6], [1,3,4,8,9,11]], [[7], [5,8,10]], [[8], [5,6,7,9,10,11]], [[9], [6,8,11]], [[10], [5,7,8], [[11], [6,8,9]]]
Asked By: KeplerNick123

||

Answers:

This is possibly a very convoluted way of doing this, but it works.

  1. Fill the diagonal of A with zeros, since you don’t want the index of the row the 1 is in.
  2. Use np.where to get the locations of the 1s.
  3. Use this answer to group by row.
  4. Use list comprehension to combine the row number and the locations of the 1s.
import numpy as np

A = np.array([[1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
              [0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
              [1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
              [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
              [0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
              [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0],
              [0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1],
              [0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
              [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1],
              [0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0],
              [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1]])

# step 1
np.fill_diagonal(A, 0)

# step 2
a = np.vstack(np.where(A == 1)).T

# step 3
k = np.split(a[:, 1], np.unique(a[:, 0], return_index=True)[1][1:])

# step 4
res = [[[i], _k.tolist()] for i, _k in enumerate(k)]

With this, we have res:

[[[0], [2, 3, 5]], [[1], [3, 4, 6]], [[2], [0, 3, 5]], [[3], [0, 1, 2, 4, 5, 6]], [[4], [1, 3, 6]], [[5], [0, 2, 3, 7, 8, 10]], [[6], [1, 3, 4, 8, 9, 11]], [[7], [5, 8, 10]], [[8], [5, 6, 7, 9, 10, 11]], [[9], [6, 8, 11]], [[10], [5, 7, 8]], [[11], [6, 8, 9]]]
Answered By: jared

The numpy approach would be to fill_diagonal, then to use where:

np.fill_diagonal(A, 0)

row, idx = np.where(A==1)  # np.where(A) if only 0/1

Output:

(array([ 0,  0,  0,  1,  1,  1,  2,  2,  2,  3,  3,  3,  3,  3,  3,  4,  4,
         4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  7,  7,  7,  8,
         8,  8,  8,  8,  8,  9,  9,  9, 10, 10, 10, 11, 11, 11]),
 array([ 2,  3,  5,  3,  4,  6,  0,  3,  5,  0,  1,  2,  4,  5,  6,  1,  3,
         6,  0,  2,  3,  7,  8, 10,  1,  3,  4,  8,  9, 11,  5,  8, 10,  5,
         6,  7,  9, 10, 11,  6,  8, 11,  5,  7,  8,  6,  8,  9]))

If you really want nested lists:

np.fill_diagonal(A, 0)

out = [[[i], np.where(a==1)[0].tolist()] for i, a in enumerate(A)]

Or:

row, idx = np.where(A==1)

x = np.array_split(idx, np.where(row[1:]!=row[:-1])[0]+1)

out = [[[i], j.tolist()] for i,j in enumerate(x)]

Output:

[[[0], [2, 3, 5]],
 [[1], [3, 4, 6]],
 [[2], [0, 3, 5]],
 [[3], [0, 1, 2, 4, 5, 6]],
 [[4], [1, 3, 6]],
 [[5], [0, 2, 3, 7, 8, 10]],
 [[6], [1, 3, 4, 8, 9, 11]],
 [[7], [5, 8, 10]],
 [[8], [5, 6, 7, 9, 10, 11]],
 [[9], [6, 8, 11]],
 [[10], [5, 7, 8]],
 [[11], [6, 8, 9]]]
Answered By: mozway
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.