#python #arrays #numpy #scipy #sparse-matrix
#python #массивы #numpy #scipy #разреженная матрица
Вопрос:
Для разреженных матриц мы обычно передаем индексы столбцов ( indices
) и indptr
вектор, который индексирует indices
вектор так, что indices[indptr[i]:indptr[i 1]]
являются элементами строки i
в разреженной матрице.
Существует ли быстрое, векторизованное, предпочтительно простое решение для преобразования вектора последовательных индексов строк в indptr
в Python?
Например, если это мой rows
вектор индексов: [0,1,1,2,2,2,3,5]
…
indptr
Вектор будет [0,1,3,6,7,7,8]
там, где 7 повторяется, потому что в векторе строк отсутствует строка 4.
Я могу сделать это с помощью простого цикла:
for i in range(len(rows)):
indptr[rows[i] 1] = 1
indptr=np.cumsum(indptr)
Но мне было интересно, есть ли более быстрый, векторизованный способ сделать это?
Комментарии:
1. в вашем коде, что такое
rows
и каковы начальные значенияindptr
? Неясно, как[0,1,3,6,7,7,8]
строится из[0,1,1,2,2,2,3,5]
2. @Ehsan rows — это индексы строк данных, и они отсортированы сверху вниз. итак, если матрица выглядит как [[1, 2], [3, 4]], массив данных был бы [1, 2, 3, 4], индексы строк будут следующими [0, 0, 1, 1], и индексы столбцов должны быть [0, 1, 0, 1]. Индексы строк, преобразованные в indptrs, будут равны [0, 2, 4].
3. Пожалуйста, посмотрите, соответствует ли опубликованный ответ тому, что вы ищете. Если это так, не стесняйтесь принять это. Если нет, пожалуйста, уточните, как вы создаете свой массив
indptr
Ответ №1:
Я думаю, что вы ищете это:
np.bincount(rows).cumsum()
#[1 3 6 7 7 8]
И если в нижней части вашей матрицы есть строки, которые могут быть пустыми, просто добавьте это в качестве аргумента в bincount
(согласно рекомендации @ CJR):
np.bincount(rows, minlength=num_rows).cumsum()
#[1 3 6 7 7 8]
Вы, вероятно, хотите также вставить 0
спереди. Что bincount
делает, так это подсчитывает количество элементов в каждой ячейке / строке, а затем cumsum
суммирует их. Таким образом, вы также включите отсутствующие ячейки / строки.
Вероятно, лучший способ вставить 0 — это:
np.bincount(np.array(rows) 1).cumsum()
#[0 1 3 6 7 7 8]
или вы можете сделать это напрямую с помощью:
np.insert(np.bincount(rows).cumsum(),0,0)
#[0 1 3 6 7 7 8]
Комментарии:
1. Убедитесь, что вы установили
minlength
в bincount значение # rows в матрице, иначе вы пропустите пустые строки в конце вашего массива indptr.
Ответ №2:
Другой идеей было бы
n = len(rows)
indptr = np.searchsorted(rows, np.arange(-1,n), side='right')
Не уверен, что быстрее / лучше