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]]]
Answers:
This is possibly a very convoluted way of doing this, but it works.
- Fill the diagonal of A with zeros, since you don’t want the index of the row the 1 is in.
- Use
np.where
to get the locations of the 1s.
- Use this answer to group by row.
- 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]]]
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]]]
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]]]
This is possibly a very convoluted way of doing this, but it works.
- Fill the diagonal of A with zeros, since you don’t want the index of the row the 1 is in.
- Use
np.where
to get the locations of the 1s. - Use this answer to group by row.
- 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]]]
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]]]