我有一个2d数组(Q),只包含0和1。我希望在每行1的每个位置填充1个Q.这是一个例子:
原始矩阵:
[0 0 0 1 0 1]
[1 0 0 0 0 0]
[0 0 0 0 0 0]
[1 1 0 1 0 0]
[1 0 0 0 0 1]
[0 1 1 0 0 1]
[1 0 1 0 1 0]
生成的矩阵:
[0 0 0 1 1 1]
[1 0 0 0 0 0]
[0 0 0 0 0 0]
[1 1 1 1 0 0]
[1 1 1 1 1 1]
[0 1 1 1 1 1]
[1 1 1 1 1 0]
我实现了一种算法,它可以工作,但是对于大型数组,它效率不高。
def beetween(Q):
for client in range(len(Q)):
idStart = findIdStart(Q, client)
idEnd = findIdEnd(Q, client)
if idStart != idEnd and idStart > -1 and idEnd > -1:
for i in range(idStart, idEnd):
Q[client][i] = 1
return Q
def findIdStart(Q, client):
if Q.ndim > 1:
l, c = np.array(Q).shape
for product in range (0, c):
if Q[client][product] == 1:
return product
else:
idProduct = 1
Qtemp = Q[client]
if Qtemp[idProduct] == 1:
return idProduct
return -1
def findIdEnd(Q, client):
if Q.ndim > 1:
l, c = np.array(Q).shape
Qtemp = Q[client]
for product in range(0,c):
idProduct = (c-1)-product
if Qtemp[idProduct]==1:
return idProduct
else:
idProduct = 1
Qtemp = Q[client]
if Qtemp[idProduct] == 1:
return idProduct
return -1
我正在尝试构建更优化的版本,但我没有取得成功:
def beetween(Q):
l, c = np.shape(Q)
minIndex = Q.argmax(axis=1)
maxIndex = c-(np.fliplr(Q).argmax(axis=1))
Q = np.zeros(shape=(l,c)).astype(np.int)
for i in range(l):
Q[i, minIndex[i]:maxIndex[i]] = 1
return Q
原始矩阵:
[0 0 0 1 0 1]
[1 0 0 0 0 0]
[0 0 0 0 0 0]
[1 1 0 1 0 0]
[1 0 0 0 0 1]
[0 1 1 0 0 1]
[1 0 1 0 1 0]
错误的结果
[0 0 0 1 1 1] # OK
[1 0 0 0 0 0] # OK
[1 1 1 1 1 1] # wrong
[1 1 1 1 0 0] # OK
[1 1 1 1 1 1] # OK
[0 1 1 1 1 1] # OK
[1 1 1 1 1 0] # OK
有人可以提出另一个解决这个问题的简单方法吗?
感谢。
答案 0 :(得分:5)
这是一个单行:
In [25]: Q
Out[25]:
array([[0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0],
[1, 0, 0, 0, 0, 1],
[0, 1, 1, 0, 0, 1],
[1, 0, 1, 0, 1, 0]])
In [26]: np.maximum.accumulate(Q, axis=1) & np.maximum.accumulate(Q[:,::-1], axis=1)[:,::-1]
Out[26]:
array([[0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0]])
或者
In [36]: np.minimum(np.maximum.accumulate(Q, axis=1), np.maximum.accumulate(Q[:,::-1], axis=1)[:,::-1])
Out[36]:
array([[0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0]])
在任何一种情况下,合并的两个术语是
In [37]: np.maximum.accumulate(Q, axis=1)
Out[37]:
array([[0, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]])
和
In [38]: np.maximum.accumulate(Q[:,::-1], axis=1)[:,::-1]
Out[38]:
array([[1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0]])
答案 1 :(得分:2)
np.apply_along_axis
的另一个选项:
import numpy as np
def minMax(A):
idx = np.where(A == 1)[0]
if len(idx) > 1:
A[idx.min():idx.max()] = 1
return A
np.apply_along_axis(minMax, 1, mat)
# array([[0, 0, 0, 1, 1, 1],
# [1, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 0, 0],
# [1, 1, 1, 1, 1, 1],
# [0, 1, 1, 1, 1, 1],
# [1, 1, 1, 1, 1, 0]])
答案 2 :(得分:1)
下面的函数查看单个行,如果存在,则在其他1之间填充1。它假定数组只包含0和1。
import numpy as np
def ones_row(row):
if np.sum(row) >= 2: # Otherwise, not enough 1s
inds = np.where(row == 1)[0]
row[inds[0]:inds[-1]] = 1
return row
现在您可以使用
处理整个数组for jj in range(len(Q)):
Q[jj] = ones_row(Q[jj])