Меня в основном интересуют двумерные массивы формы Nx3, но проблема возникает также в массивах форм Nxm, где m> 1. В частности, я хотел бы отсортировать массив Nx3 сначала на основе его первого столбца, затем второго и, наконец, третьего. Итак, предполагая, что у нас есть массив k
, заданный как
array([[0.90625, 0.90625, 0.15625],
[0.40625, 0.40625, 0.15625],
[0.40625, 0.90625, 0.65625],
[0.15625, 0.90625, 0.40625],
[0.90625, 0.40625, 0.90625],
[0.40625, 0.65625, 0.15625],
[0.40625, 0.65625, 0.65625],
[0.15625, 0.65625, 0.40625],
[0.65625, 0.15625, 0.90625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.90625, 0.40625],
[0.65625, 0.40625, 0.40625],
[0.15625, 0.15625, 0.90625],
[0.40625, 0.40625, 0.40625],
[0.65625, 0.90625, 0.40625],
[0.90625, 0.15625, 0.40625]])
, требуемый (отсортированный) массив должен быть
array([[0.15625, 0.15625, 0.90625],
[0.15625, 0.65625, 0.40625],
[0.15625, 0.90625, 0.40625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.15625],
[0.40625, 0.40625, 0.40625],
[0.40625, 0.65625, 0.15625],
[0.40625, 0.65625, 0.65625],
[0.40625, 0.90625, 0.40625],
[0.40625, 0.90625, 0.65625],
[0.65625, 0.15625, 0.90625],
[0.65625, 0.40625, 0.40625],
[0.65625, 0.90625, 0.40625],
[0.90625, 0.15625, 0.40625],
[0.90625, 0.40625, 0.90625],
[0.90625, 0.90625, 0.15625]])
Я думал, что смогу добиться этого, используя np.lexsort
, но кажется, что я что-то упустил и не работает, как ожидалось. До сих пор я делал следующее:
In [28]: k[np.lexsort((k[:,2], k[:,1], k[:,0]))]
Out[28]:
array([[0.15625, 0.65625, 0.40625],
[0.15625, 0.15625, 0.90625],
[0.15625, 0.90625, 0.40625],
[0.40625, 0.65625, 0.65625],
[0.40625, 0.90625, 0.40625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.40625],
[0.40625, 0.90625, 0.65625],
[0.40625, 0.40625, 0.15625],
[0.40625, 0.65625, 0.15625],
[0.65625, 0.15625, 0.90625],
[0.65625, 0.90625, 0.40625],
[0.65625, 0.40625, 0.40625],
[0.90625, 0.40625, 0.90625],
[0.90625, 0.15625, 0.40625],
[0.90625, 0.90625, 0.15625]])
Кажется, что первый столбец отсортирован правильно, а остальные нет. Подобный вопрос был задан до , но я считаю, что принятый ответ (что я и делаю) не работает.
Из того, что я понял после более подробного изучения, я думаю, что это связано со значениями массива, являющегося float.
EDIT
Я нашел ответ на мою проблему. Однако я добавлю его как «редактировать», а не публиковать как ответ, потому что я полагаю, что этой ситуации можно было бы избежать, если бы я упомянул тонкую деталь о матрице k
в своем первоначальном посте. Матрица k
создается из другой матрицы a
, где a
по существу создается путем чтения из файла матрицы с плавающей запятой с 16 десятичными знаками. Теперь давайте посмотрим на рабочий процесс, который привел меня к решению.
In [6]: k=a[[1,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60]]
In [7]: k
Out[7]:
array([[0.15625, 0.15625, 0.40625],
[0.15625, 0.40625, 0.15625],
[0.15625, 0.65625, 0.15625],
[0.15625, 0.90625, 0.15625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.15625],
[0.40625, 0.65625, 0.15625],
[0.40625, 0.90625, 0.15625],
[0.65625, 0.15625, 0.15625],
[0.65625, 0.40625, 0.15625],
[0.65625, 0.65625, 0.15625],
[0.65625, 0.90625, 0.15625],
[0.90625, 0.15625, 0.15625],
[0.90625, 0.40625, 0.15625],
[0.90625, 0.65625, 0.15625],
[0.90625, 0.90625, 0.15625]])
In [8]: np.random.shuffle(k)
In [9]: k
Out[9]:
array([[0.15625, 0.90625, 0.15625],
[0.90625, 0.40625, 0.15625],
[0.40625, 0.65625, 0.15625],
[0.90625, 0.90625, 0.15625],
[0.15625, 0.40625, 0.15625],
[0.65625, 0.15625, 0.15625],
[0.40625, 0.90625, 0.15625],
[0.65625, 0.65625, 0.15625],
[0.40625, 0.15625, 0.15625],
[0.90625, 0.65625, 0.15625],
[0.65625, 0.40625, 0.15625],
[0.15625, 0.65625, 0.15625],
[0.65625, 0.90625, 0.15625],
[0.15625, 0.15625, 0.40625],
[0.90625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.15625]])
In [10]: k[np.lexsort((k[:,2],k[:,1],k[:,0]))]
Out[10]:
array([[0.15625, 0.40625, 0.15625],
[0.15625, 0.65625, 0.15625],
[0.15625, 0.90625, 0.15625],
[0.15625, 0.15625, 0.40625],
[0.40625, 0.65625, 0.15625],
[0.40625, 0.90625, 0.15625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.15625],
[0.65625, 0.15625, 0.15625],
[0.65625, 0.40625, 0.15625],
[0.65625, 0.65625, 0.15625],
[0.65625, 0.90625, 0.15625],
[0.90625, 0.15625, 0.15625],
[0.90625, 0.40625, 0.15625],
[0.90625, 0.65625, 0.15625],
[0.90625, 0.90625, 0.15625]])
In [11]: k=np.round(k, 5)
In [12]: k[np.lexsort((k[:,2],k[:,1],k[:,0]))]
Out[12]:
array([[0.15625, 0.15625, 0.40625],
[0.15625, 0.40625, 0.15625],
[0.15625, 0.65625, 0.15625],
[0.15625, 0.90625, 0.15625],
[0.40625, 0.15625, 0.15625],
[0.40625, 0.40625, 0.15625],
[0.40625, 0.65625, 0.15625],
[0.40625, 0.90625, 0.15625],
[0.65625, 0.15625, 0.15625],
[0.65625, 0.40625, 0.15625],
[0.65625, 0.65625, 0.15625],
[0.65625, 0.90625, 0.15625],
[0.90625, 0.15625, 0.15625],
[0.90625, 0.40625, 0.15625],
[0.90625, 0.65625, 0.15625],
[0.90625, 0.90625, 0.15625]])
In [13]: np.savetxt(sys.stdout, a[[1,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60]], fmt='%.18f')
0.156250000000000000 0.156250000000000000 0.406250000000000000
0.156249999999999972 0.406250000000000000 0.156250000000000028
0.156249999999999972 0.656250000000000000 0.156250000000000028
0.156249999999999972 0.906250000000000000 0.156250000000000028
0.406250000000000000 0.156249999999999972 0.156250000000000028
0.406250000000000000 0.406250000000000000 0.156250000000000028
0.406249999999999944 0.656250000000000000 0.156250000000000028
0.406249999999999944 0.906250000000000000 0.156250000000000028
0.656250000000000000 0.156249999999999972 0.156250000000000028
0.656250000000000000 0.406249999999999944 0.156250000000000028
0.656250000000000000 0.656250000000000000 0.156250000000000028
0.656250000000000000 0.906250000000000000 0.156250000000000056
0.906250000000000000 0.156249999999999972 0.156250000000000028
0.906250000000000000 0.406249999999999944 0.156250000000000028
0.906250000000000000 0.656250000000000000 0.156250000000000056
0.906250000000000000 0.906250000000000000 0.156250000000000056
Как видно из вышесказанного, все это было связано с ошибками округления. По-видимому, все было хорошо, когда печаталось с несколькими десятичными знаками, но когда файл был прочитан и была создана матрица a
, он был сохранен с неточностями после 16-го знака после запятой. Следовательно, эти неточности были доведены до k
, когда оно было определено с a
. Поэтому lexsort
с самого начала давал правильный результат, учитывая реальное число, которое было сохранено в матрице. Все работало нормально, когда я округлил матрицу k
.
Мораль истории: всегда проверяйте точность ваших ценностей.