Numpy memmap на месте сортировка большой матрицы по столбцам

#python #numpy #python-3.6 #memmap

#python #numpy #python-3.6 #memmap

Вопрос:

Я хотел бы отсортировать матрицу формы (N, 2) по первому столбцу, где N >> системная память.

С помощью numpy в памяти вы можете сделать:

 x = np.array([[2, 10],[1, 20]])
sortix = x[:,0].argsort()
x = x[sortix]
  

Но, похоже, для этого требуется, чтобы она x[:,0].argsort() помещалась в память, что не будет работать для memmap, где N >> системная память (пожалуйста, поправьте меня, если это предположение неверно).

Могу ли я добиться такой сортировки на месте с помощью numpy memmap?

(предположим, что для сортировки используется heapsort и используются простые числовые типы данных)

Ответ №1:

Решение может быть простым, используя аргумент order для сортировки на месте. Конечно, order требуются имена полей, поэтому их нужно добавить в первую очередь.

 d = x.dtype
x = x.view(dtype=[(str(i), d) for i in range(x.shape[-1])])
array([[(2, 10)],
   [(1, 20)]], dtype=[('0', '<i8'), ('1', '<i8')])
  

Имена полей представляют собой строки, соответствующие индексам столбцов. Сортировка может быть выполнена на месте с помощью

 x.sort(order='0', axis=0)
  

Затем преобразуйте обратно в обычный массив с исходным типом данных

 x.view(d)
array([[ 1, 20],
   [ 2, 10]])
  

Это должно сработать, хотя вам может потребоваться изменить способ просмотра в зависимости от того, как данные хранятся на диске, см. Документы

Для.view(some_dtype), если some_dtype имеет другое количество байтов на запись, чем предыдущий dtype (например, преобразование обычного массива в структурированный массив), то поведение view нельзя предсказать только по внешнему виду a (показано print(a)). Это также зависит от того, как именно a хранится в памяти. Поэтому, если a упорядочен по C, а не по fortran, а не определен как срез или транспонирование и т.д., представление может давать разные результаты.

Ответ №2:

@user2699 прекрасно ответил на вопрос. Я добавляю это решение в качестве упрощенного примера на случай, если вы не возражаете сохранить свои данные в виде структурированного массива, что устраняет представление.

 import numpy as np

filename = '/tmp/test'
x = np.memmap(filename, dtype=[('index', '<f2'),('other1', '<f2'),('other2', '<f2')], mode='w ', shape=(2,))
x[0] = (2, 10, 30)
x[1] = (1, 20, 20)
print(x.shape)
print(x)
x.sort(order='index', axis=0, kind='heapsort')
print(x)

(2,)
[(2., 10., 30.) (1., 20., 20.)]
[(1., 20., 20.) (2., 10., 30.)]
  

Также здесь задокументированы форматы dtype.