Индексирование двухмерного массива numpy с одномерной матрицей numpy [duplicate]

var clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (var i in this) {
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        }
        else
        {
            newObj[i] = this[i];
        }
    }
    return newObj;
}; 

Object.defineProperty( Object.prototype, "clone", {value: clone, enumerable: false});
149
задан Alex Riley 3 March 2015 в 21:40
поделиться

7 ответов

Как отметил Свен, x[[[0],[2]],[1,3]] вернет 0 и 2 строки, соответствующие столбцам 1 и 3, а x[[0,2],[1,3]] вернет значения x [0,1] и x [2,3] в массиве ,

В первом примере, который я дал, numpy.ix_, есть полезная функция. Вы можете сделать то же самое, что и мой первый пример с x[numpy.ix_([0,2],[1,3])]. Это может избавить вас от необходимости вводить во все эти дополнительные скобки.

45
ответ дан Justin Peel 21 August 2018 в 04:21
поделиться

У меня есть аналогичный вопрос здесь: Написание в sub-ndarray ndarray на самом пифоновском пути. Python 2 .

Следуя решению предыдущего сообщения для вашего случая, решение выглядит так:

columns_to_keep = [1,3] 
rows_to_keep = [1,3]

Использование ix _:

x[np.ix_(rows_to_keep, columns_to_keep)] 

Который есть:

array([[ 5,  7],
       [13, 15]])
2
ответ дан Rafael Valero 21 August 2018 в 04:21
поделиться

Чтобы ответить на этот вопрос, мы должны посмотреть, как индексирование многомерного массива работает в Numpy. Давайте сначала скажем, что у вас есть массив x из вашего вопроса. Буфер, назначенный x, будет содержать 16 восходящих целых чисел от 0 до 15. Если вы обращаетесь к одному элементу, скажем x[i,j], NumPy должен определить расположение памяти этого элемента относительно начала буфера. Это делается путем вычисления фактического значения i*x.shape[1]+j (и умножения на размер int для получения фактического смещения памяти).

Если вы извлекаете подмассив с помощью базовой нарезки, такой как y = x[0:2,0:2], результирующий объект будет совместно использовать базовый буфер с помощью x. Но что произойдет, если вы получите y[i,j]? NumPy не может использовать i*y.shape[1]+j для вычисления смещения в массиве, поскольку данные, принадлежащие y, не являются последовательными в памяти.

NumPy решает эту проблему, введя шаги . При вычислении смещения памяти для доступа к x[i,j] то, что на самом деле вычисляется, является i*x.strides[0]+j*x.strides[1] (и это уже включает в себя коэффициент для размера int):

x.strides
(16, 4)

Когда извлечено y как и выше, NumPy не создает новый буфер, но делает создание нового объекта массива, ссылающегося на тот же буфер (иначе y будет просто равен x.) Новый объект массива будет имеют другую форму, тогда x и, возможно, другое начальное смещение в буфере, но будут делиться шагами с x (в этом случае, по крайней мере):

y.shape
(2,2)
y.strides
(16, 4)

Таким образом, вычисляя смещение памяти для y[i,j] даст правильный результат.

Но что делать NumPy для чего-то вроде z=x[[1,3]]? Механизм шагов не позволит правильно проиндексировать, если исходный буфер используется для z. NumPy теоретически мог бы добавить еще более сложный механизм, чем шаги, но это сделало бы доступ к элементу относительно дорогостоящим, как-то игнорируя всю идею массива. Кроме того, представление больше не будет действительно легким объектом.

Это подробно описано в документации NumPy по индексированию .

О, и почти забыл о вашем фактическом вопросе: вот как сделать индексацию с несколькими списками работать как ожидалось:

x[[[1],[3]],[1,3]]

Это связано с тем, что массивы индексов транслируются на общий форма. Конечно, в этом конкретном примере вы также можете заниматься базовым нарезкой:

x[1::2, 1::2]
102
ответ дан rubenvb 21 August 2018 в 04:21
поделиться
  • 1
    Может быть возможным подклассифицировать массивы так, чтобы можно было иметь «разрез», объект, который будет переназначать индексы в исходный массив. Возможно, это может удовлетворить потребности ОП – jsbueno 23 November 2010 в 16:44
  • 2
    @jsbueno: это будет работать для кода Python, но не для подпрограмм C / Fortran, которые обертывают Scipy / Numpy. Те обернутые подпрограммы - это то, где лежит сила Numpy. – Dat Chu 23 November 2010 в 18:45
  • 3
    Су. В чем разница между x [[[1], [3]], [1,3]] и x [[1,3],:] [:, [1,3]]? Я имею в виду, есть ли вариант, который лучше использовать, чем другой? – levesque 23 November 2010 в 21:49
  • 4
    @JC: x[[[1],[3]],[1,3]] создает только один новый массив, а x[[1,3],:][:,[1,3]] копирует дважды, поэтому используйте первый. – Sven Marnach 24 November 2010 в 11:48
  • 5
    – Sven Marnach 24 November 2010 в 12:05

Я не думаю, что x[[1,3]][:,[1,3]] вряд ли читаем. Если вы хотите быть более ясными в своих намерениях, вы можете сделать:

a[[1,3],:][:,[1,3]]

Я не эксперт в разрезе, но обычно, если вы пытаетесь нарезать массив и значения непрерывны, вы верните представление, в котором изменяется значение шага.

например На ваших входах 33 и 34, хотя вы получаете массив 2x2, шаг равен 4. Таким образом, при индексировании следующей строки указатель перемещается в правильное положение в памяти.

Ясно, что этот механизм не работает хорошо переносятся на массив индексов. Следовательно, numpy должен будет сделать копию. В конце концов, многие другие математические функции матрицы зависят от размера, шага и непрерывного выделения памяти.

11
ответ дан Simon 21 August 2018 в 04:21
поделиться

Если вы хотите пропустить каждую другую строку и каждый другой столбец, вы можете сделать это с помощью базовой нарезки:

In [49]: x=np.arange(16).reshape((4,4))
In [50]: x[1:4:2,1:4:2]
Out[50]: 
array([[ 5,  7],
       [13, 15]])

Это возвращает представление, а не копию вашего массива.

In [51]: y=x[1:4:2,1:4:2]

In [52]: y[0,0]=100

In [53]: x   # <---- Notice x[1,1] has changed
Out[53]: 
array([[  0,   1,   2,   3],
       [  4, 100,   6,   7],
       [  8,   9,  10,  11],
       [ 12,  13,  14,  15]])

, в то время как z=x[(1,3),:][:,(1,3)] использует расширенную индексацию и, таким образом, возвращает копию:

In [58]: x=np.arange(16).reshape((4,4))
In [59]: z=x[(1,3),:][:,(1,3)]

In [60]: z
Out[60]: 
array([[ 5,  7],
       [13, 15]])

In [61]: z[0,0]=0

Обратите внимание, что x не изменяется:

In [62]: x
Out[62]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

Если вы хотите выбрать произвольные строки и столбцы, тогда вы не можете использовать базовую нарезку. Вам нужно будет использовать расширенную индексацию, используя что-то вроде x[rows,:][:,columns], где rows и columns - это последовательности. Это, конечно же, даст вам копию, а не представление, вашего исходного массива. Это так, как и следовало ожидать, поскольку массив numpy использует непрерывную память (с постоянными шагами), и не было бы способа создать представление с произвольными строками и столбцами (поскольку для этого потребовались бы непостоянные шаги).

9
ответ дан unutbu 21 August 2018 в 04:21
поделиться

С помощью numpy вы можете передать срез для каждого компонента индекса, поэтому ваш пример x[0:2,0:2] выше работает.

Если вы просто хотите равномерно пропускать столбцы или строки, вы можете передать срезы с тремя компонентами (например, start, stop, step).

Опять же, для вашего примера выше:

>>> x[1:4:2, 1:4:2]
array([[ 5,  7],
       [13, 15]])

В основном это: срез в первом измерении, с началом с индексом 1, остановка, когда индекс равен или больше 4, и добавить 2 к индексу в каждом проходе. То же самое для второго измерения. Опять же: это работает только для постоянных шагов.

Синтаксис, который вам нужно сделать во всем, что-то совсем другое - фактически x[[1,3]][:,[1,3]] создает новый массив, включающий только строки 1 и 3 из исходного массива (сделано с частью x[[1,3]]), а затем повторно разрезать это: создание третьего массива - включая только столбцы 1 и 3 предыдущего массива.

5
ответ дан yoniLavi 21 August 2018 в 04:21
поделиться
  • 1
    Это решение не работает, поскольку оно специфично для строк / столбцов, которые я пытался извлечь. Представьте себе то же самое в матрице 50x50, когда я хочу извлечь строки / столбцы 5,11,12,32,39,45, нет способа сделать это с помощью простых срезов. Извините, если я не понял в своем вопросе. – levesque 23 November 2010 в 17:30
0
ответ дан Valery Marcel 31 October 2018 в 23:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: