Python numpy: размер [0] в векторах (n-dim) против массивов (nxn-dim)

102
8

Мне сейчас интересно, как ведет себя массив numpy. Я чувствую, что размеры не согласуются с векторами (размерность Nx1) до "реальных массивов" (размерность NxN).

Я не понимаю, почему это не работает:

a = array(([1,2],[3,4],[5,6]))
concatenate((a[:,0],a[:,1:]), axis = 1)
# ValueError: all the input arrays must have same number of dimensions

Кажется, что :1:]) имеет значение, но (:0 не работает)

Заранее спасибо!

Detailled Version: Поэтому я ожидал бы, что shape(b)[0] ссылается на вертикальное направление в (массивы Nx1), как в массиве 2D (NxN). Но похоже, что размер [0] - это горизонтальное направление в массивах (массивы Nx1)?

from numpy import *

a = array(([1,2],[3,4],[5,6]))
b = a[:,0]
print shape(a) # (3L, 2L), [0] is vertical
print a # [1,2],[3,4],[5,6]
print shape(b) # (3L, ), [0] is horizontal
print b # [1 3 5]

c = b * ones((shape(b)[0],1))
print shape(c) # (3L, 3L), I'd expect (3L, 1L)
print c # [[ 1. 3. 5.], [ 1. 3. 5.], [ 1. 3. 5.]]

Что я ошибся? Есть ли лучший способ, чем

d = b * ones((1, shape(b)[0]))
d = transpose(d)
print shape(d) # (3L, 1L)
print d # [[ 1.], [ 3.], [ 5.]]

получить (Nx1) вектор, который я ожидаю или хочу?

спросил(а) 2021-01-19T14:52:35+03:00 9 месяцев назад
1
Решение
79

Здесь есть две общие проблемы. Во-первых, b не является (N, 1) образным массивом, это массив (N,). В numpy 1D и 2D массивы - разные вещи. 1D массивы просто не имеют направления. Вертикальные или горизонтальные, строки и столбцы - это 2D-концепции.

Второе связано с тем, что называется " трансляция ". В массивах numpy вы можете транслировать низкоразмерные массивы на более крупные, а нижнемерная часть применяется элементарно к высокомерному.

Правила вещания довольно просты:

При работе на двух массивах NumPy сравнивает свои фигуры по элементам. Он начинается с конечных размеров и работает вперёд. Два измерения совместимы, когда

они равны или

один из них - 1

В вашем случае он начинается с последнего измерения ones((shape(b)[0],1)), который равен 1. Это соответствует второму критерию. Поэтому он умножает массив b elementwise для каждого элемента из ones((shape(b)[0],1)), в результате чего получается 3D-массив.

Таким образом, это примерно эквивалентно:

c = np.array([x*b for x in ones(shape(b))])

Редактировать:

Чтобы ответить на ваш первоначальный вопрос, вы хотите сохранить как первый, так и второй массивы в виде 2D-массивов.

numpy есть очень простое правило для этого: индексирование уменьшает количество измерений, нарезка - нет. Так что вам нужно только иметь 1-й фрагмент. Поэтому в вашем примере просто измените a[:,0] на a[:,:1]. Это означает, что "каждый столбец до второго". Конечно, это включает только первый столбец, но он по-прежнему считается операцией среза, а не получает элемент, поэтому он все еще сохраняет количество измерений:

>>> print(a[:, 0])
[1 3 5]
>>> print(a[:, 0].shape)
(3,)
>>> print(a[:, :1])
[[1]
[3]
[5]]
>>> print(a[:, :1].shape)
(3, 1)
>>> print(concatenate((a[:,:1],a[:,1:]), axis = 1))
[[1 2]
[3 4]
[5 6]]

ответил(а) 2021-01-19T14:52:35+03:00 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема