Оптимизирован контейнер для ввода с набранными предметами? - PullRequest
0 голосов
/ 03 мая 2019

У меня есть большой (типизированный) массив из набора данных, в котором первый столбец содержит уникальный ключ для индексации каждой строки, а другие столбцы содержат матрицы или векторы известного размера.Есть ли какой-либо стандартный способ или библиотека, чтобы эффективно превратить это в хэш-карту для поиска на основе ключей?Разделение строки на отдельные объекты значения ключа не кажется эффективным с точки зрения памяти.

Вот базовое неоптимальное решение:

arr = np.array([
    ('b0263', 'a', 1, 2, 3),
    ('26ab0', 'b', 4, 5, 6),
    ('6d7fc', 'c', 7, 8, 9),
    ('48a24', 'd', 0, 1, 2),
    ('1dcca', 'e', 3, 4, 5)],
    dtype="S5, c, i4, i4, i4")
out = {key: values for key, *values in arr}

Я думал о диктовке, содержащей целочисленные индексысоответствующих строк, но требуется два уровня индексации.

1 Ответ

0 голосов
/ 03 мая 2019

Ваш структурированный массив:

In [317]: arr                                                                        
Out[317]: 
array([(b'b0263', b'a', 1, 2, 3), (b'26ab0', b'b', 4, 5, 6),
       (b'6d7fc', b'c', 7, 8, 9), (b'48a24', b'd', 0, 1, 2),
       (b'1dcca', b'e', 3, 4, 5)],
      dtype=[('f0', 'S5'), ('f1', 'S1'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4')])

Первое поле:

In [318]: arr['f0']                                                                  
Out[318]: array([b'b0263', b'26ab0', b'6d7fc', b'48a24', b'1dcca'], dtype='|S5')

Словарь, построенный из этого массива:

In [321]: dd = {k:v for k,v in zip(arr['f0'], arr)}                                  
In [322]: dd                                                                         
Out[322]: 
{b'b0263': (b'b0263', b'a', 1, 2, 3),
 b'26ab0': (b'26ab0', b'b', 4, 5, 6),
 b'6d7fc': (b'6d7fc', b'c', 7, 8, 9),
 b'48a24': (b'48a24', b'd', 0, 1, 2),
 b'1dcca': (b'1dcca', b'e', 3, 4, 5)}
In [323]: dd[b'6d7fc']                                                               
Out[323]: (b'6d7fc', b'c', 7, 8, 9)

В этой конструкции значение элемента словаря является элементом исходного массива.

Имеет type np.void и dtype:

In [329]: dd[b'6d7fc'].dtype                                                         
Out[329]: dtype([('f0', 'S5'), ('f1', 'S1'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4')])

И это на самом деле view оригинала (я проверил __array_interface__). Так что кроме указателей / ссылок он не потребляет много дополнительной памяти.

В последних версиях numpy переработана обработка представлений / копий структурированных массивов, поэтому детали могут измениться, особенно в отношении ссылок на несколько полей.

Я должен квалифицировать комментарий памяти. В этом примере itemsize равно 18. Но ссылаясь на элемент массива, arr[0] создает новый объект np.void. Я подозреваю, что объем служебных данных превышает 18 байт.

Вы можете создать словарь со значениями кортежа:

In [335]: dd = {k:v.tolist()[1:] for k,v in zip(arr['f0'], arr)}                     
In [336]: dd[b'b0263']                                                               
Out[336]: (b'a', 1, 2, 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...