У меня есть матрица данных a
и список индексов, хранящихся в массиве idx
. Я хотел бы получить данные длиной 10, начиная с каждого из индексов, определенных idx
. Прямо сейчас я использую цикл for
для достижения этой цели. Но это очень медленно, так как мне приходится делать выборку этих данных около 1000 раз за итерацию. Ниже приведен минимальный рабочий пример.
import numpy as np
a = np.random.random(1000)
idx = np.array([1, 5, 89, 54])
# I want "data" array to have np.array([a[1:11], a[5:15], a[89:99], a[54:64]])
# I use for loop below but it is slow
data = []
for id in idx:
data.append(a[id:id+10])
data = np.array(data)
Можно ли как-то ускорить этот процесс? Спасибо.
Обновлено: Мой вопрос отличается от заданного здесь. В вопросе размер фрагментов является случайным, в отличие от фиксированного размера фрагмента в моем вопросе. Существуют и другие различия. Мне не нужно использовать весь массив a
, и элемент может встречаться более чем в одном фрагменте. Мой вопрос не обязательно «разделяет» массив.
@ Иван, ха-ха, да. Я отредактировал его, чтобы теперь он имел случайные значения.
это сложнее, потому что есть перекрывающиеся разделы! Если вы сделаете np.split(a, idx)
, вы разделите массив на индексы 1
, 5
оставив вас с [array of size 1, array of size 4, ...
, что не является желаемым результатом.
(Благодаря предложению @MadPhysicist)
Это должно работать:
a[idx.reshape(-1, 1) + np.arange(10)]
Выход:
Форма (L,10)
, где L
- длина idx
Примечания:
Это не проверяет ситуации выхода за границы индекса. Я полагаю, что сначала легко убедиться, что idx
не содержит таких значений.
Использование np.take(a, idx.reshape(-1, 1) + np.arange(10), mode='wrap')
является альтернативой, которая будет обрабатывать индексы за пределами границ, оборачивая их вокруг a
. Передача mode='clip'
вместо mode='wrap'
обрезает лишние индексы до последнего индекса a
. Но тогда у np.take()
, вероятно, была бы совершенно другая производительность. характеристика / характеристика масштабирования.
Я думаю, что было бы быстрее отсортировать индекс, особенно для коротких массивов. +1 в любом случае
Кроме того, вам действительно не нужно изменять форму и транспонировать. Выходной массив представляет собой форму индекса. idx.reshape(-1, 1) + np.arange(10)
достаточно
@MadPhysicist - Спасибо, отредактировано с упрощением.
Мы можем увидеть изменения в истории редактирования. Не нужно отмечать «редактировать» и «обновить» в вопросах и ответах. Это распространенное заблуждение среди начинающих авторов, что люди хотят видеть что-то кроме вашего отточенного продукта.
Я предполагаю, что
a
это единицы для целей вопроса, верно?