2017-05-26 72 views

回答

3

一个量化的方法,利用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.]]) 
+0

这很好,但是我在理解它背后的逻辑时有点麻烦。 – bnicholl

+0

@bnicholl一步一步来。使用一个示例,运行每个步骤,查看输出并按照那样进行操作。使用我发布的评论:'基本上这些步骤是:..'。这应该有所帮助。 – Divakar

+0

好的,我明白了。以前从未使用过像这样的numpy bool数组。倒数第二行,就在退货声明将我抛弃之前。我无法理解0是如何被置于虚假指数中的。我想它只是如何numpy蒙面阵列的工作 – bnicholl

0

我不知道如何直接在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) 
0
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.]] 
0

随着每行包含至少一个零的假设,并没有否定,这只是一个分区:

>>> np.partition(x, 1) 
array([[ 0., 0., 5., 2.], 
     [ 0., 0., 3., 2.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 2., 1.]]) 

编辑:这慢腾腾行,所以是好一点比这更好

+0

不知道这个真的,例如假设一行是:[[0.,6.,3.,2.]',它给出:[[0.,2.,3.,6。],'。 – Divakar

+1

Docs说:'两个分区中元素的排序是未定义的。所以,你必须另外使用'argsort',然后进行高级索引以保持顺序。 – Divakar

+0

的确如此 - 只有在订单无关紧要时才有用。我做了一个编辑 – Eric