Как построить массив, подходящий для сортировки чисел?
Вопрос
Мне нужно сортировать два массива одновременно, или, скорее, мне нужно отсортировать один из массивов и перенести с ним соответствующий элемент связанного с ним массива при сортировке.То есть, если массив имеет вид [(5, 33), (4, 44), (3, 55)] и я сортирую по первой оси (помеченной ниже dtype='alpha'), тогда я хочу:[(3,0, 55,0) (4,0, 44,0) (5,0, 33,0)].Это действительно большие наборы данных, и мне нужно сначала отсортировать их (для скорости nlog(n)), прежде чем выполнять какие-либо другие операции.Я не знаю, как правильно объединить два отдельных массива, чтобы алгоритм сортировки работал.Я думаю, что моя проблема довольно проста.Я попробовал три разных метода:
import numpy
x=numpy.asarray([5,4,3])
y=numpy.asarray([33,44,55])
dtype=[('alpha',float), ('beta',float)]
values=numpy.array([(x),(y)])
values=numpy.rollaxis(values,1)
#values = numpy.array(values, dtype=dtype)
#a=numpy.array(values,dtype=dtype)
#q=numpy.sort(a,order='alpha')
print "Try 1:\n", values
values=numpy.empty((len(x),2))
for n in range (len(x)):
values[n][0]=y[n]
values[n][1]=x[n]
print "Try 2:\n", values
#values = numpy.array(values, dtype=dtype)
#a=numpy.array(values,dtype=dtype)
#q=numpy.sort(a,order='alpha')
###
values = [(x[0], y[0]), (x[1],y[1]) , (x[2],y[2])]
print "Try 3:\n", values
values = numpy.array(values, dtype=dtype)
a=numpy.array(values,dtype=dtype)
q=numpy.sort(a,order='alpha')
print "Result:\n",q
Я закомментировал первую и вторую попытки, потому что они создают ошибки. Я знал, что третья сработает, потому что она отражает то, что я видел, когда был RTFM.Учитывая массивы x и y (которые очень большие, показаны только примеры), как мне создать массив (называемый значениями), который может правильно вызываться с помощью numpy.sort?
*** Zip работает отлично, спасибо.Бонусный вопрос:Как мне позже снова разархивировать отсортированные данные в два массива?
Решение
Я думаю, что вам нужна функция zip.Если у вас есть
x = [1,2,3]
y = [4,5,6]
затем zip(x,y) == [(1,4),(2,5),(3,6)]
Таким образом, ваш массив может быть построен с использованием
a = numpy.array(zip(x,y), dtype=dtype)
Другие советы
для вашего бонусного вопроса - zip тоже распаковывается:
In [1]: a = range(10)
In [2]: b = range(10, 20)
In [3]: c = zip(a, b)
In [4]: c
Out[4]:
[(0, 10),
(1, 11),
(2, 12),
(3, 13),
(4, 14),
(5, 15),
(6, 16),
(7, 17),
(8, 18),
(9, 19)]
In [5]: d, e = zip(*c)
In [6]: d, e
Out[6]: ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19))
Саймон предложил аргументированная сортировка как альтернативный подход;Я бы порекомендовал это как путь.Никакого беспорядочного слияния, сжатия или разархивирования:просто доступ по индексу.
idx = numpy.argsort(x)
ans = [ (x[idx[i]],y[idx[i]]) for i in idx]
zip()
мощь быть неэффективным для больших массивов. numpy.dstack()
можно использовать вместо zip
:
ndx = numpy.argsort(x)
values = numpy.dstack((x[ndx], y[ndx]))
Я думаю, вам просто нужно указать ось, по которой вы сортируете, когда вы создадите окончательный ndarray.В качестве альтернативы выполните argsort один из исходных массивов, и у вас будет индексный массив, который вы можете использовать для поиска как по x, так и по y, что может означать, что вам вообще не нужны значения.
(кажется, scipy.org сейчас недоступен, иначе я бы разместил вам ссылку на некоторые документы)
Учитывая, что ваше описание не совсем соответствует вашему фрагменту кода, трудно сказать с уверенностью, но я думаю, что вы слишком усложнили создание своего массива numpy.
Я не смог получить рабочее решение, используя Numpy sort
функция, но вот что-то еще, что работает:
import numpy
x = [5,4,3]
y = [33,44,55]
r = numpy.asarray([(x[i],y[i]) for i in numpy.lexsort([x])])
lexsort
возвращает перестановку индексов массива, которая упорядочивает строки в отсортированном порядке.Если вы хотите, чтобы ваши результаты были отсортированы по нескольким ключам, например.к x
а затем y
, использовать numpy.lexsort([x,y])
вместо.