I have a numpy array that looks like this:
The size can be changed by altering the 'row_num' and 'col_num' variables
[[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]]
During the program, the array may look like this:
[[0. 0. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 1. 0. 1. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 2. 0. 2. 0. 0.]
[2. 2. 0. 0. 0. 0. 0.]
[1. 1. 0. 0. 0. 1. 0.]]
I am trying to make a function to move number down the bottom, like gravity. So once the function has run, the array would look like:
[[0. 0. 0. 0. 0. 0. 0.]
[2. 2. 0. 0. 0. 0. 0.]
[1. 1. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 1. 0. 1. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 2. 0. 2. 1. 0.]]
Currently, the code inside my function looks like:
for cols in range(col_num):
for rows in range(row_num-1):
if board[rows][cols] == 0 and board[rows 1][cols] == 1:
board[rows 1][cols] = 0
board[rows][cols] = 1
print('move down 1')
elif board[rows][cols] == 0 and board[rows 1][cols] == 2:
board[rows 1][cols] = 0
board[rows][cols] = 2
print('move down 2')
The print statements are working so the condition is being met, but it does not change the array
CodePudding user response:
One way to achieve your desired out is to use python's builtin sort
method.
In [2]: data
Out[2]:
array([[0., 0., 0., 0., 0., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 1., 0., 1., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 2., 0., 2., 0., 0.],
[2., 2., 0., 0., 0., 0., 0.],
[1., 1., 0., 0., 0., 1., 0.]])
In [3]: np.array([sorted(column, key=bool) for column in data.T]).T
Out[3]:
array([[0., 0., 0., 0., 0., 0., 0.],
[2., 2., 0., 0., 0., 0., 0.],
[1., 1., 0., 0., 0., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 1., 0., 1., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 2., 0., 2., 1., 0.]])
This sorts every "non-zero" element after all "zeros".
CodePudding user response:
You could follow this approach:
import numpy as np
import pandas as pd
arr = np.array([[0., 0., 0., 0., 0., 0.,0.],
[2.,2.,2.,0.,2.,0.,0.],
[1.,1.,1.,0.,1.,0.,0.],
[2.,2.,2.,0.,2.,0.,0.],
[1.,1.,2.,0.,2.,0.,0.],
[2.,2.,0.,0.,0.,0.,0.],
[1.,1.,0.,0.,0.,1.,0.]])
arr_t = np.array(list(zip(*arr)))
print(np.array(list(zip(*[np.concatenate([line[line == 0], line[line =! 0]]) for line in arr_t]))))
OUTPUT
[[0. 0. 0. 0. 0. 0. 0.]
[2. 2. 0. 0. 0. 0. 0.]
[1. 1. 0. 0. 0. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 1. 0. 1. 0. 0.]
[2. 2. 2. 0. 2. 0. 0.]
[1. 1. 2. 0. 2. 1. 0.]]
You transpose the bidimensional array, for each line you build an array where you concatenate the array of 0s to all the other numbers, and at the end to re transpose it
CodePudding user response:
We can use argsort
to get indices that would sort the given array in such a way that numbers would align to bottom, then use np.take_along_axis
to sort the array using the indices
i = (arr != 0).argsort(axis=0)
np.take_along_axis(arr, i, axis=0)
array([[0., 0., 0., 0., 0., 0., 0.],
[2., 2., 0., 0., 0., 0., 0.],
[1., 1., 0., 0., 0., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 1., 0., 1., 0., 0.],
[2., 2., 2., 0., 2., 0., 0.],
[1., 1., 2., 0., 2., 1., 0.]])