2016-08-19 4 views
1

Для того, чтобы сцепить массив 1D к 2D массива, следующее исправление предлагается:Какова логика необходимости преобразования 1D-массива в 2D для конкатенации?

A = np.array([1, 2, 3]) 
B = np.array([[4, 5],[6,7],[8,9]]) 

# np.hstack((A,B)) 
# throws "ValueError: all the input arrays must have same number of dimensions" 

np.hstack((A[:, None],B)) #works 

Может кто-то пожалуйста, объясните логику этого? (со ссылкой?)

Исходя из фона matlab, это требование является неинтуитивным.

Спасибо!

ответ

0

Я думаю, что причина этой разницы между numpy и MATLAB - это разница в философии и дизайне.

Пакет numpy разработан с большим упором на интеграцию с языком программирования python и со стандартными типами переменных, которые находятся на языке программирования python. С другой стороны, MATLAB сконструирован вокруг матриц.

Основным типом данных в MATLAB является матрица, так что даже то, что выглядит как число с плавающей запятой, действительно является матрицей 1 x 1. Вы можете увидеть доказательства here, что MATLAB спроектирован с матрицей в качестве основного типа.

Однако в numpy массивы, которые используются, являются более близкими родственниками к одномерным и многомерным массивам на языке программирования python. Таким образом, numpy предоставляет относительно общие методы, такие как concatenate и split, которые поддерживают аргумент, определяющий, на какую ось многомерного массива они должны работать. В достаточно недавних версиях (с 1.10) существует также метод stack, который может добавлять измерение по мере его конкатенации. Страница here является ссылкой на различные методы манипуляции с массивами в версии 1.11, включая три упомянутые мной и методы hstack и column_stack.

Кстати, есть другие способы получить одну и ту же матрицу результатов. Две возможности, которые могли бы апеллировать немного больше пользователей MATLAB являются

np.hstack((np.atleast_2d(A).T, B)) 

и

np.hstack((A.reshape([A.size,1]), B)) 

Кроме того, это технически возможно извлечь столбцы из B в 1-мерных массивов и построить матрицу вы хотите для создания путем объединения друг с другом массивов с 1-D.В более старых версиях numpy объединение 1-мерных массивов в матрицу использует vstack и транспонирование. Это может выглядеть следующим образом

np.vstack([A] + [B[:,j] for j in xrange(B.shape[1])]).T 

или, если вы хотите использовать более Numpy манипуляции массива команд вместо нарезки, она может быть записана

np.vstack([A] + [np.squeeze(c) for c in np.hsplit(B, B.shape[1])]).T 
1

Документ hstack():

numpy.hstack (стро) [источник] Стек массивы в последовательности по горизонтали (колонка стрелки).

Возьмите последовательность массивов и соедините их по горизонтали, чтобы создать один массив . Перестройте массивы, разделенные hsplit.

Параметры: tup: последовательность ndarrays Все массивы должны иметь одинаковую форму вдоль всей, кроме второй оси. Возвращает: stacked: ndarray массив , образованный путем укладки данных массивов.

последовательность ndarrays Все массивы должны иметь одинаковую форму вдоль всех, кроме второй оси.

A[:, None] создает новый массив с формой (3, 1), это 2D массив, как B, так hstack() работы.

Вы можете использовать вместо:

np.c_[A, B] 
np.column_stack((A, B)) 
+1

В случае, если кто хочет ссылке: // документы .scipy.org/doc/numpy-1.10.1/reference/generated/numpy.hstack.html – zachyee

+0

Чтобы понять, я понимаю, что hstack принимает только массивы определенной формы. Я пытаюсь понять, ПОЧЕМУ существуют отдельные функции hstack и column_stack, которые имеют эти ограничения. – DataOR

+0

Я попытался объяснить больше того, что делают hstack и 'column_stack'. – hpaulj

1

Посмотрите на эти массивы:

In [26]: A 
Out[26]: array([1, 2, 3]) 
In [27]: B 
Out[27]: 
array([[4, 5], 
     [6, 7], 
     [8, 9]]) 
In [28]: A[:,None] 
Out[28]: 
array([[1], 
     [2], 
     [3]]) 

In [31]: np.concatenate([A[:,None],B],axis=1) 
Out[31]: 
array([[1, 4, 5], 
     [2, 6, 7], 
     [3, 8, 9]]) 

Разве это не имеет смысла, что если вы хотите присоединиться к 3 предметов A в 3 ряда B, что A также должен иметь 3 строки?

Большая разница между numpy и MATLAB заключается в том, что в MATLAB все равно 2d (или выше). В массивах numpy может быть 1d и разностные матрицы. Сравнение

Октава:

>> A=[1,2,3] 
A = 

    1 2 3 

>> B=[4,5;6,7;8,9] 
B = 

    4 5 
    6 7 
    8 9 

The (1,3) не может быть соединена с (3,2) матрицы в любом направлении:

>> cat(1,A,B) 
error: cat: dimension mismatch 
>> cat(2,A,B) 
error: cat: dimension mismatch 

Но это работает, если я транспонировать A:

>> cat(2,A.',B) 
ans = 

    1 4 5 
    2 6 7 
    3 8 9 

Таким образом, даже при использовании 2-й базовой линии размеры должны соответствовать.

Все hstack добавлено к concatenate: atleast_1d, что в данном случае не помогает. np.column_stack делает его 2d и .T, поэтому он работает.Я рекомендую посмотреть базовый код для таких функций, как hstack и column_stack (у вас, возможно, уже есть привычка от MATLAB).

==================

Ваш комментарий о разнице между hstack и column_stack. У них нет особых ограничений, скорее они просто делают разные вещи, чтобы приспособить размеры своих входных данных. Ничто не делает ничего глубокого или загадочного.

def hstack(tup): 
    arrs = [np.atleast_1d(m) for m in tup] 
    return np.concatenate(arrs, 0) # used when A is first 
    # return np.concatenate(arrs, 1) # used when B is first 

Поскольку оба массива по крайней мере 1d, первый шаг ничего не добавляет. Так что это просто вопрос того, чтобы пытаться сделать

np.concatenate((A,B), axis=0) # or axis=1 

В любом случае пытается сцепить (3,) массив в (3,2) не работает - один 1d, другой 2d. A (3,1) с (3,2) работает, если вы хотите (3,3). В этом случае A.ndim<2; шаг array превращает A в (1,3), а T изменяет его на (3,1). Это то же самое, что и A[:,None].

Значит, это np.concatenate, что накладывает ограничения - сопоставление ndim и соответствующий размер по соответствующему размеру. Функции stack являются просто удобными инструментами и не делают ничего, что вы не можете сделать напрямую.

Смежные вопросы