I have a 2d array ( Q
) consisting of only zeros and ones (binary matrix). For each column of Q
I want to find the index of the first and last row which the value 1 occurs. Each column contains at least one 1
.
Here's an example:
[[1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0],
[1, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 1, 0]]
boundsList = {0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}
I implemented an algorithm, it works, but for large arrays it is not efficient:
boundsList = {}
for i in range (0, len(Q)):
column = Q[:,i]
indexesList = []
for idx, pos in enumerate (column):
if pos == 1:
indexesList.append(idx)
boundsList[i] = (indexesList[0], indexesList[-1])
Can anybody could suggest another simple solution to this problem?
Let's start with your array:
>>> Q
array([[1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0],
[1, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 0, 1, 1],
[1, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 1, 0]])
To obtain the indices for each column of the first row which contains 1:
>>> np.argmax(Q, axis=0) # Index of first appearance of 1
array([0, 0, 0, 1, 2, 3, 2])
To obtain the indices for each column of the last row which contains 1:
>>> Q.shape[0] - np.argmax(Q[::-1, :], axis=0) - 1 # Index of last appearance of 1
array([4, 1, 5, 6, 2, 6, 5])
To combine them into a dictionary of your liking:
>>> dict(enumerate(zip( np.argmax(Q, axis=0), Q.shape[0] - np.argmax(Q[::-1, :], axis=0) - 1)))
{0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}
Probably the fastest way would be to use the argmax
method (it works because it finds the position of the first maximum) from both sides and then put that in a dictionary. The argmax
method has far less overhead (constant factor) than using np.argmax
so, especially for small arrays, the method will be much faster.
Because dict
, enumerate
and zip
are faster on lists than arrays I also convert the intermediate arrays to lists (the tolist
method is the fastest way to achieve that):
>>> dict(enumerate(zip(Q.argmax(axis=0).tolist(),
... (Q.shape[0]-1-Q[::-1].argmax(axis=0)).tolist())))
{0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}
The Q[::-1]
is the reversed array and to get the "not-reversed" indices I have to subtract them from Q.shape[0]-1
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.