如果我有一個numpy的陣列類似下面,我怎樣才能右對齊或左對齊TAT的元素大於零的Python:大於0移動的所有元素以左,右numpy的陣列
[[ 0. 5. 0. 2.]
[ 0. 0. 3. 2.]
[ 0. 0. 0. 0.]
[ 2. 0. 0. 1.]]
例如,如果我想右對齊這個數組,它看起來像:
[[ 5. 2. 0. 0.]
[ 3. 2. 0. 0.]
[ 0. 0. 0. 0.]
[ 2. 1. 0. 0.]]
如果我有一個numpy的陣列類似下面,我怎樣才能右對齊或左對齊TAT的元素大於零的Python:大於0移動的所有元素以左,右numpy的陣列
[[ 0. 5. 0. 2.]
[ 0. 0. 3. 2.]
[ 0. 0. 0. 0.]
[ 2. 0. 0. 1.]]
例如,如果我想右對齊這個數組,它看起來像:
[[ 5. 2. 0. 0.]
[ 3. 2. 0. 0.]
[ 0. 0. 0. 0.]
[ 2. 1. 0. 0.]]
一個量化的方法,利用masks
的 -
def justify_rows(a, side='left'):
mask = a>0
justified_mask = np.sort(mask,1)
if side=='left':
justified_mask = justified_mask[:,::-1]
out = np.zeros_like(a)
out[justified_mask] = a[mask]
return out
基本上步驟是:
製作的掩模大於零大。
獲取一個左對齊或右對齊的掩碼,其中大於元素將放置在零初始化數組中。爲了得到這樣一個合理的掩碼,我們只需沿着每一行對步驟1中的掩碼進行排序,這會將每行中的True
引導到右側。因此,另外我們需要爲左對齊的情況翻轉每行。
最後,使用合理的掩碼分配到輸出數組和從步驟1的掩碼從輸入數組中選擇。
樣品試驗 -
In [105]: a
Out[105]:
array([[ 0., 5., 0., 2.],
[ 0., 0., 3., 2.],
[ 0., 0., 0., 0.],
[ 2., 0., 0., 1.]])
In [106]: justify_rows(a, side='left')
Out[106]:
array([[ 5., 2., 0., 0.],
[ 3., 2., 0., 0.],
[ 0., 0., 0., 0.],
[ 2., 1., 0., 0.]])
In [107]: justify_rows(a, side='right')
Out[107]:
array([[ 0., 0., 5., 2.],
[ 0., 0., 3., 2.],
[ 0., 0., 0., 0.],
[ 0., 0., 2., 1.]])
我不知道如何直接在numpy
做到這一點。你可以通過利用Timsort穩定的優勢在Python循環中完成它,但它不會是速度顛簸。
import numpy as np
A = np.array([
[0., 5., 0., 2.],
[0., 0., 3., 2.],
[0., 0., 0., 0.],
[2., 0., 0., 1.],
])
zero = A.dtype.type()
for row in A:
row[:] = sorted(row, key=zero.__lt__)
# right-justified
print(A)
for row in A:
row[:] = sorted(row, key=zero.__lt__, reverse=True)
# left-justified
print(A)
import numpy as np
array = [
[ 0., 5., 0., 2.],
[ 0., 0., 3., 2.],
[ 0., 0., 0., 0.],
[ 2., 0., 0., 1.]
]
def move(array, right = True):
temp = []
for x in array:
x = np.array(x)
#check positive arrays
if len(np.where(x == 0)[0]) != len(x):
if right:
# little faster, compare to [::-1]
# nonzero on right
temp.append(x[np.argsort(-x)])
else:
# nonzero on left
temp.append(np.sort(x))
else:
# no interchange needed
temp.append(x)
return temp
print (move(array, 1))
[array([ 5., 2., 0., 0.]), array([ 3., 2., 0., 0.]), array([ 0., 0., 0., 0.]), array([ 2., 1., 0., 0.])]
print (move(array, 0))
[array([ 0., 0., 2., 5.]), array([ 0., 0., 2., 3.]), array([ 0., 0., 0., 0.]), array([ 0., 0., 1., 2.])]
print (np.concatenate(list(zip(move(array, 1))), axis=0))
[[ 5. 2. 0. 0.]
[ 3. 2. 0. 0.]
[ 0. 0. 0. 0.]
[ 2. 1. 0. 0.]]
隨着每行包含至少一個零的假設,並沒有否定,這只是一個分區:
>>> np.partition(x, 1)
array([[ 0., 0., 5., 2.],
[ 0., 0., 3., 2.],
[ 0., 0., 0., 0.],
[ 0., 0., 2., 1.]])
編輯:這慢騰騰行,所以是好一點比這更好
這很好,但是我在理解它背後的邏輯時有點麻煩。 – bnicholl
@bnicholl一步一步來。使用一個示例,運行每個步驟,查看輸出並按照那樣進行操作。使用我發佈的評論:'基本上這些步驟是:..'。這應該有所幫助。 – Divakar
好的,我明白了。以前從未使用過像這樣的numpy bool數組。倒數第二行,就在退貨聲明將我拋棄之前。我無法理解0是如何被置於虛假指數中的。我想它只是如何numpy蒙面陣列的工作 – bnicholl