#python #arrays #numpy #sorting #sequence
Вопрос:
У меня есть массив 2D numpy, подобный этому:
[[4 5 2]
[5 5 1]
[5 4 5]
[5 3 4]
[5 4 4]
[4 3 2]]
Я хотел бы отсортировать / кластеризировать этот массив, найдя последовательность в массиве следующим row[0]>=row[1]>=row[2]
образом , row[0]>=row[2]>row[1]
… таким образом, строка массива находится в упорядоченной последовательности.
Я пытался использовать код: lexdf = df[np.lexsort((df[:,2], df[:,1],df[:,0]))][::-1]
, однако я этого не хочу. Вывод lexsort:
[[5 5 1]
[5 4 5]
[5 4 4]
[5 3 4]
[4 5 2]
[4 3 2]]
Результат, который я хотел бы иметь:
[[5 5 1]
[5 4 4]
[4 3 2]
[5 4 5]
[5 3 4]
[4 5 2]]
или разбейте его на три части:
[[5 5 1]
[5 4 4]
[4 3 2]]
[[5 4 5]
[5 3 4]]
[[4 5 2]]
И я хотел бы применить это к массиву с большим количеством столбцов, поэтому было бы лучше сделать это без итерации. Есть идеи для создания такого вывода?
Комментарии:
1. Ваша нотация нестандартна, что затрудняет отслеживание вашего описания
2. Что это
row[0]>=row[1]>=row[2]
такое?3. @MadPhysicist Я хотел бы отсортировать строки в 2D-массиве на основе столбца. Это
row[0]>=row[1]>row[2]
означает, что нужно найти строки в этом массиве, чтобы значение в первом столбце было больше или равно значению во втором столбце, а значение во втором столбце больше, чем значение в третьем столбце.4. Я до сих пор не понимаю, как вы переходите от этого к желаемому результату. Возможно, вы могли бы написать функцию сравнения, которую вы могли бы использовать для сортировки, или ключ сортировки? В принципе, однозначно покажите, как вы бы решили, какая строка идет первой.
5. Звучит как проблема с графом: учитывая ориентированный граф, разделите граф на простые деревья (без каких-либо ветвей).
Ответ №1:
Я не знаю, как это сделать в numpy, за исключением, может быть, некоторых странных хаков функций numpy.split
.
Вот способ получить ваши группы с помощью списков python:
from itertools import groupby, pairwise
def f(sublist):
return [x <= y for x,y in pairwise(sublist)]
# NOTE: itertools.pairwise requires python>=3.10
# For python<=3.9, use one of those alternatives:
# * more_itertools.pairwise(sublist)
# * zip(sublist, sublist[1:])
a = [[4, 5, 2],
[5, 5, 1],
[5, 4, 5],
[5, 3, 4],
[5, 4, 4],
[4, 3, 2]]
b = [list(g) for _,g in groupby(sorted(a, key=f), key=f)]
print(b)
# [[[4, 3, 2]],
# [[5, 4, 5], [5, 3, 4], [5, 4, 4]],
# [[4, 5, 2], [5, 5, 1]]]
Примечание: комбинация groupby sorted на самом деле немного неэффективна, поскольку sorted
занимает n логарифмическое (n) время. Линейной альтернативой является группирование с использованием словаря списков. См., Например, Функцию itertoolz.groupby
из модуля toolz
.
Комментарии:
1. Спасибо! Это действительно то, что мне нужно. Просто небольшая вещь, если я хочу получить желаемый результат, этого
x < y
не должно бытьx <= y
. Я хотел бы спросить еще одну вещь, если это возможно: если я хотел бы сравнить только значения первых нескольких столбцов, а не весь столбец, что мне делать? Например, я хочу сравнить только первые два столбца.2. Я уже нашел способ! Спасибо за ваше понимание!