Как отсортировать двухмерный массив в коде по количеству нулей в строке?
Есть массив, некоторые элементы которого равны нулю. Нужно отсортировать его по количеству нулей в строках, кроме последнего столбца. Где строка с наибольшим количеством нулей будет последней, а с наименьшим или без - первой.
Вообще, это решение нужно для перестановки строк матрицы в привычный вид для решения СЛАУ.
Код:
import copy
import numpy as np
def maxArr(arr):
max = abs(arr[0][0])
for i in range(len(arr)):
for j in range(len(arr)):
if max < abs(arr[i][j]):
max = abs(arr[i][j])
row = i
col = j
return max, row, col
def printArr(arr):
for i in range(len(arr)):
for j in range(len(arr[i])):
print("%2.4f" % (arr[i][j]), end = ' ')
print(" ")
print(" ")
arrM = np.array([[3.81, 0.25, 1.28, 1.75, 4.21],
[2.25, 1.32, 5.58, 0.49, 7.47],
[5.31, 7.28, 0.98, 1.04, 2.38],
[10.39, 2.45, 3.35, 2.28, 11.48]]);
arrR = copy.copy(arrM)
arrY = np.array([[0.0] * len(arrM[0])] * len(arrM))
x = [0] * len(arrM)
r = [0] * len(arrM)
for k in range(len(arrM)):
print("Матрица M[" + str(k) + "]: ")
printArr(arrM)
max, p, q = maxArr(arrM)
m = [0] * len(arrM)
for i in range(len(arrM)):
if i != p:
# подсчет коеф. м
m[i] = -(arrM[i][q]/arrM[p][q])
for j in range(len(arrM[i])):
# умножаем элементы неглавных строк на коеф. м
arrM[i][j] += arrM[p][j]*m[i]
#"вычеркиваем" элементы главной строчки
for i in range(len(arrM[0])):
arrY[p][i] = arrM[p][i]
arrM[p][i] = 0
print("Результат прямого хода: ")
printArr(arrY)
Конкретно в моем коде нужно преобразить массив arrY из такого
0.0000 -0.0000 0.0000 0.9005 -0.3449
0.0000 -0.0000 4.9504 0.0127 5.4406
0.0000 6.0279 -0.7321 -0.1252 -3.4871
10.3900 2.4500 3.3500 2.2800 11.4800
в такой
10.3900 2.4500 3.3500 2.2800 11.4800
0.0000 6.0279 -0.7321 -0.1252 -3.4871
0.0000 -0.0000 4.9504 0.0127 5.4406
0.0000 -0.0000 0.0000 0.9005 -0.3449
Мне подсказали такое решение, но оно не работает с моим кодом.
printArr(arrY[(arrY==0).sum(axis=1).argsort()])
Ответы (1 шт):
По-моему "проблема" в том, что в вашей матрице встречаются значения, которые стремятся к нулю, но при строгом сравнении с нулем выдают False, о чем вы забыли упомянуть в вопросе:
In [11]: arrY
Out[11]:
array([[ 0.00000000e+00, -6.09777900e-19, 0.00000000e+00, 9.00524911e-01, -3.44918767e-01],
[ 0.00000000e+00, -1.11022302e-16, 4.95041956e+00, 1.26575251e-02, 5.44063920e+00],
[ 0.00000000e+00, 6.02788258e+00, -7.32078922e-01, -1.25235804e-01, -3.48706449e+00],
[ 1.03900000e+01, 2.45000000e+00, 3.35000000e+00, 2.28000000e+00, 1.14800000e+01]])
поэтому можно воспользоваться np.isclose(...):
In [14]: printArr(arrY[np.isclose(arrY, 0, atol=1e-07).sum(axis=1).argsort()])
10.3900 2.4500 3.3500 2.2800 11.4800
0.0000 6.0279 -0.7321 -0.1252 -3.4871
0.0000 -0.0000 4.9504 0.0127 5.4406
0.0000 -0.0000 0.0000 0.9005 -0.3449
UPD: в решении выше с нулем сравниваются все столбцы, включая последний. Если последний столбец сравнивать не нужно, то это делается так:
res = arrY[np.isclose(arrY[:, :-1], 0, atol=1e-07).sum(axis=1).argsort()]