Построить индекс Numpy с учетом списка начальных и конечных позиций - PullRequest
4 голосов
/ 16 января 2011

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

Например:

import numpy as np
start = np.array([1,7,20])
end = np.array([3,10,25])

Хочу ссылку

somearray[1,2,7,8,9,20,21,22,23,24])

Ответы [ 4 ]

4 голосов
/ 17 января 2011

Я бы использовал

np.r_[tuple(slice(s, e) for s, e in zip(start, end))]

РЕДАКТИРОВАТЬ: Вот решение, которое не использует цикл Python:

def indices(start, end):
    lens = end - start
    np.cumsum(lens, out=lens)
    i = np.ones(lens[-1], dtype=int)
    i[0] = start[0]
    i[lens[:-1]] += start[1:]
    i[lens[:-1]] -= end[:-1]
    np.cumsum(i, out=i)
    return i

Это создает только один временный массив NumPy (lens) и работает намного быстрее, чем любое другое решение.

2 голосов
/ 16 января 2011

Numpy's arange создает каждую отдельную последовательность, поэтому просто связывайте их вместе.Как насчет этого?

In [11]: idx = np.hstack([np.arange(s,e) for s,e in  zip(start, end)])

In [12]: idx
Out[12]: array([ 1,  2,  7,  8,  9, 20, 21, 22, 23, 24])

И тогда вы можете получить доступ к somearray[idx].

0 голосов
/ 17 января 2011

Как насчет этого:

>>> import numpy as np
>>> start = np.array([1,7,20])
>>> end = np.array([3,10,25])
>>> na=np.fromiter(sum([range(s,e) for s,e in zip(start,end)],[]),np.int)
>>> na
array([ 1,  2,  7,  8,  9, 20, 21, 22, 23, 24])

Преимущество состоит в том, что 1) нет промежуточных массивов с поплавковыми числами;2) результирующий массив является целым числом для наиболее эффективного обращения к другим массивам.

0 голосов
/ 16 января 2011

Вы заявили, что «в качестве альтернативы вы можете сказать, что у меня есть список начальных позиций и длин окон», который не соответствует вашему массиву примеров.

Если start обозначает начало, а end - это длина , вы можете получить свои элементы следующим образом:

>>> [i for iter in [range(s,s+e) for s,e in zip(start,end)] for i in iter]
[1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 21, 22, 23, 24, 25, 26, 
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]

Если вы хотите сопоставить ваш пример массива, а end действительно является конечным элементом -1 , вы можете получить свои элементы следующим образом:

>>> [i for iter in [range(*t) for t in zip(start,end)] for i in iter]
[1, 2, 7, 8, 9, 20, 21, 22, 23, 24]
>>> somearray=np.array(_)
>>> somearray
array([1, 2, 7, 8, 9, 20, 21, 22, 23, 24])

Альтернатива:

>>> sum([range(*t) for t in zip(start,end)],[])
[1, 2, 7, 8, 9, 20, 21, 22, 23, 24]

Имейте в виду, что вы просто генерируете список целых чисел, описанных в ваших кортежах как индекс вашего массива numpy. Любой из них может использовать xrange против range, если в вашем случае это быстрее / лучше .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...