A = np.arange(40).reshape(4,10)*.1
startend = [[2,5],[3,6],[4,7],[5,8]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([13, 14, 15]), array([24, 25, 26]), array([35, 36, 37])]
A.flat[index_list]
производства
array([[ 0.2, 0.3, 0.4],
[ 1.3, 1.4, 1.5],
[ 2.4, 2.5, 2.6],
[ 3.5, 3.6, 3.7]])
Это все еще имеет итерации, но это довольно элементарное один над списком. Я индексирую сплющенную, 1d, версию A
. np.take(A, index_list)
также работает.
Если интервалы строк отличаются по размеру, я могу использовать np.r_
, чтобы объединить их. Это не совсем необходимо, но это удобство при создании индексов из нескольких интервалов и значений.
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.3, 1.4, 1.5, 2.4, 2.5, 2.6, 3.5, 3.6, 3.7])
idx
, что ajcr
использование может быть использована без choose
:
idx = [np.arange(v[0], v[1]) for i,v in enumerate(startend)]
A[np.arange(A.shape[0])[:,None], idx]
idx
как мой index_list
за исключением того, что он не добавляет длину строки.
np.array(idx)
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
Поскольку каждый arange
имеет ту же длину, idx
могут быть получены без итерации:
col_start = np.array([2,3,4,5])
idx = col_start[:,None] + np.arange(3)
Первый индекс представляет собой массив столбец, который транслирует, чтобы соответствовать этому idx
.
np.arange(A.shape[0])[:,None]
array([[0],
[1],
[2],
[3]])
С этим A
и idx
я получаю следующие тайминги:
In [515]: timeit np.choose(idx,A.T[:,:,None])
10000 loops, best of 3: 30.8 µs per loop
In [516]: timeit A[np.arange(A.shape[0])[:,None],idx]
100000 loops, best of 3: 10.8 µs per loop
In [517]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 24.9 µs per loop
flat
индексация происходит быстрее, но вычисления индекса любитель занимает некоторое время.
Для больших массивов доминирует скорость индексации flat
.
A=np.arange(4000).reshape(40,100)*.1
col_start=np.arange(20,60)
idx=col_start[:,None]+np.arange(30)
In [536]: timeit A[np.arange(A.shape[0])[:,None],idx]
10000 loops, best of 3: 108 µs per loop
In [537]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 59.4 µs per loop
np.choose
метод работает в закодированный предел: Need between 2 and (32) array objects (inclusive).
Что из границ idx
?
col_start=np.array([2,4,6,8])
idx=col_start[:,None]+np.arange(3)
A[np.arange(A.shape[0])[:,None], idx]
выдает ошибку, потому что последний idx
значение 10
, слишком велик.
Вы могли clip
idx
idx=idx.clip(0,A.shape[1]-1)
производить повторяющиеся значения в последней строке
[ 3.8, 3.9, 3.9]
Вы могли бы также площадку A
перед индексированием. Дополнительную информацию см. В разделе np.pad
.
np.pad(A,((0,0),(0,2)),'edge')[np.arange(A.shape[0])[:,None], idx]
Другим вариантом является удаление значений за пределами границ. idx
тогда станет оборванным списком списков (или массивом списков). Подход flat
может справиться с этим, хотя результат не будет матрицей.
startend = [[2,5],[4,7],[6,9],[8,10]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([14, 15, 16]), array([26, 27, 28]), array([38, 39])]
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.4, 1.5, 1.6, 2.6, 2.7, 2.8, 3.8, 3.9])
Да, но можете ли вы предоставить лучший пример? – dursk
В примере (|) находятся элементы, к которым я хочу обратиться, (.) - это другие элементы. Хочешь узнать что-нибудь еще? – recodeFuture
@tjons: что убеждает вас в том, что мы работаем со словарем? OP повторно ссылается на массив; OP добавила тег 'numpy'; представление выглядит намного больше, чем представление массива, чем словарь; и т.п. – DSM