Решение
Я искал и в прошлом, и в настоящем решение этой проблемы с открытым исходным кодом, но я не нашел такого, который удовлетворял бы мой аппетит. На этот раз я решил начать строить свой собственный и открыто обсуждать его реализацию, которая также охватывает случай null
, то есть сценарий пропущенных данных.
Обратите внимание, что вторичный индекс очень близок к представлению списка смежности, ключевому элементу в моем TRIADB проекте, и это является основной причиной поиска решения.
Давайте начнем с однострочного кода, используя numpy
idx = np.sort(np.array(list(zip(pk, val)), dtype=struct_type), order='val')
idx['val']
Out[68]:
array([ 2.1 , 3.75, 7.2 , 15.5 , 142.88, 142.88, nan, nan,
nan], dtype=float32)
idx['pk']
Out[69]: array([8, 1, 7, 0, 2, 3, 4, 5, 6], dtype=uint32)
Более быстрое решение ( less generi c)
это особый, но вполне допустимый случай, когда pk имеет значения в диапазоне (n)
idx_pk = np.argsort(val)
idx_pk
Out[91]: array([8, 1, 7, 0, 2, 3, 4, 5, 6])
idx_val = val[idx_pk]
idx_val
Out[93]: array([ 2.1 , 3.75, 7.2 , 15.5 , 142.88, 142.88, nan, nan, nan], dtype=float32)
Существует еще несколько шагов для получения представления вторичного индекса согласно определению СП. D'Silva и др.
- Избавиться от
nan
- Рассчитать уникальные значения вторичного индекса
- Для каждого уникального значения рассчитать список индексов первичного ключа ко всем строкам таблицы, которые содержат это значение
Уникальный вторичный индекс со списками смежности
def secondary_index_with_adjacency_list(arr):
idx_pk = np.argsort(arr)
idx_val = arr[idx_pk]
cnt = np.count_nonzero(~np.isnan(idx_val))
usec_ndx, split_ndx, cnt_arr = np.unique(idx_val[:cnt], return_index=True, return_counts=True)
adj_list = np.split(idx_pk[:cnt], split_ndx)[1:]
return usec_ndx, cnt_arr, adj_list
ndx, freq, adj = secondary_index_with_adjacency_list(val)
pd.DataFrame({'val': ndx, 'freq': freq, 'adj': adj})
Out[11]:
val freq adj
0 2.10 1 [8]
1 3.75 1 [1]
2 7.20 1 [7]
3 15.50 1 [0]
4 142.88 2 [2, 3]
Обсуждение
На практике это быстрее использовать представление вторичного индекса с повторяющимися значениями, чем со списками указателей на записи таблицы, но второй обладает интересным свойством быть ближе к представлению гиперграфа, которое я использую в TRIADB .
Тип вторичного индекса, описанный в этом решении, больше подходит для анализа, фильтрации больших наборов данных, которые не помещаются в память, но хранятся на диске в формате хранилища столбцов. В этом случае для указанного c набора столбцов можно восстановить подмножество записей в формате памяти (хранилище столбцов) и даже представить его на гиперграфе (следите за обновлениями для следующего выпуска TRIADB)