如果我有一个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