Python: moving all elements greater than 0 left and right in a numpy array

If I have a numpy array like the one below, how can I justify correctly or leave the alignment of tat elements greater than zero

[[ 0.  5.  0.  2.]
 [ 0.  0.  3.  2.]
 [ 0.  0.  0.  0.]
 [ 2.  0.  0.  1.]]

For example, if I wanted to justify this array, it would look like this:

[[ 5.  2.  0.  0.]
 [ 3.  2.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 2.  1.  0.  0.]]
+4
source share
4 answers

One vector approach using 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

Mainly stages:

  • Make a mask bigger than zeros.

  • , , , . ​​ , -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.]])
+3

, numpy. Python, Timsort, , .

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

With the assumption that each line contains at least one zero, and not negative ones, this is just a section:

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

Edit: this moves the lines, so a little better than sorting

0
source

Source: https://habr.com/ru/post/1678016/


All Articles