Транспонирование массива NumPy


193

Я использую Python и NumPy и у меня есть некоторые проблемы с «transpose»:

import numpy as np
a = np.array([5,4])
print(a)
print(a.T)

Вызов a.Tне транспонирует массив. Если aэто, например, [[],[]]то он правильно транспонирует, но мне нужно транспонировать [...,...,...].


также пытался "print a.transpose", который является тем же, но без успеха, не транспонировать ...
Thaking

Ответы:


247

Это работает точно так, как и должно. Транспонирование одномерного массива все еще является одномерным массивом! (Если вы привыкли к matlab, у него принципиально нет концепции одномерного массива. Матрицы "1D" в Matlab являются двумерными.)

Если вы хотите превратить свой 1D-вектор в 2D-массив, а затем транспонировать его, просто нарежьте его np.newaxis(или Noneони одинаковы, newaxisпросто более читабельно).

import numpy as np
a = np.array([5,4])[np.newaxis]
print(a)
print(a.T)

Вообще говоря, вам не нужно беспокоиться об этом. Добавление дополнительного измерения обычно не то, что вы хотите, если вы просто делаете это по привычке. Numpy автоматически транслирует одномерный массив при выполнении различных вычислений. Обычно нет необходимости различать вектор строки и вектор столбца (ни один из которых не является вектором . Они оба 2D!), Когда вам нужен только вектор.


2
@thaking - я просто np.arangeбыстро создавал одномерный массив. Это работает точно так же для a = np.array([5,4]).
Джо Кингтон

2
@thaking Если вы новичок в numpy - имейте в виду, что круглые скобки ()не указывают на дополнительное измерение в numpy. Если a = np.arange(10)затем aв array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])качестве производства a.__repr__(). Это одномерный (то есть a.ndim --> 1) вектор, как указано в квадратных скобках []. array( ... )Не видно , когда вы либо print(a)или a.__str__().
dtlussier

7
@JoeKington есть ситуация, когда трансляция одномерного массива полезна. Вычисление расстояния между всеми 1D точками в массиве. Благодаря вашему решению можно сделать x - x [np.newaxis] .T, который дает матрицу расстояний
JuanPi

4
Лично я считаю , np.vstack()работа будет более явным: print np.vstack(a).
Александр Позднеев

2
Это не просто Matlab, но линейная алгебра имеет понятие вектора строки / столбца. Numpy уникален для людей, приезжающих из разных мест, а не только из Matlab.
Эрик

135

Используйте две пары скобок вместо одной. Это создает 2D-массив, который можно транспонировать, в отличие от 1D-массива, который вы создаете, если используете одну пару скобок.

import numpy as np    
a = np.array([[5, 4]])
a.T

Более подробный пример:

>>> a = [3,6,9]
>>> b = np.array(a)
>>> b.T
array([3, 6, 9])         #Here it didn't transpose because 'a' is 1 dimensional
>>> b = np.array([a])
>>> b.T
array([[3],              #Here it did transpose because a is 2 dimensional
       [6],
       [9]])

Используйте shapeметод numpy, чтобы увидеть, что здесь происходит:

>>> b = np.array([10,20,30])
>>> b.shape
(3,)
>>> b = np.array([[10,20,30]])
>>> b.shape
(1, 3)

11
Я предпочитаю это решение [np.newaxis], оно выглядит более изящным, по моему мнению.
PhilMacKay

Машины не такие умные. Даже если у вас есть только одна жена, она должна быть объявлена ​​вашей первой женой.
Sreeragh AR

Это должен быть выбранный ответ
Бруно

79

Для одномерных массивов :

a = np.array([1, 2, 3, 4])
a = a.reshape((-1, 1)) # <--- THIS IS IT

print a
array([[1],
       [2],
       [3],
       [4]])

Как только вы поймете, что здесь -1 означает «столько строк, сколько необходимо», я нахожу, что это наиболее читаемый способ «транспонирования» массива. Если ваш массив имеет большую размерность, просто используйте a.T.


5
Обратите внимание, что это работает только с векторами. Если у вас есть двумерный массив, операции transposeи reshapeизменение массива выполняются по- разному (результирующая форма изображения одинакова, но элементы размещаются по-разному).
Johndodo

2
Спасибо за ваше замечание. Я понимаю вашу точку зрения, но я думаю, что это отвлекает больше, чем разъясняет мой ответ, потому что я даю простое однострочное решение точного вопроса, который @thaking создает. Это не о 2-х массивах, а о 1-х. Яблоки и груши здесь.
Ульф Аслак

2
Конечно. Ваш ответ правильный и элегантный для этого случая, я никогда не хотел его критиковать. Но, учитывая название вопроса («Транспонирование массива NumPy»), я подозреваю, что многие посетители придут сюда в поисках более общего решения, и я хотел предупредить их, что оно неприменимо к 2D-массивам. В противном случае ваш ответ является правильным и подходящим с учетом вопроса ОП.
Johndodo

@UlfAslak, пожалуйста, уточните свой ответ, что ваш подход не обобщается на массив ND, всегда хорошо быть предельно ясным, как предложено! Johndodo, чтобы никто не использовал вашу технику неправильно.!, Вопрос здесь для правильного ответа & не лайнер.
Anu

18

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

from numpy import *
v=array([5,4]) ## create a numpy vector
array([v]).T ## transpose a vector into a matrix

Numpy также имеет matrixкласс (см. массив против матрицы ) ...

matrix(v).T ## transpose a vector into a matrix

14

массив 1D -> матрица столбец / строка:

>>> a=np.array([1,2,4])
>>> a[:, None]    # col
array([[1],
       [2],
       [4]])
>>> a[None, :]    # row, or faster `a[None]`
array([[1, 2, 4]])

И как сказал @ Джо-Kington, вы можете заменить Noneс np.newaxisдля удобства чтения.


10

Чтобы «транспонировать» 1d массив в 2d столбец, вы можете использовать numpy.vstack:

>>> numpy.vstack(numpy.array([1,2,3]))
array([[1],
       [2],
       [3]])

Это также работает для списков ванили:

>>> numpy.vstack([1,2,3])
array([[1],
       [2],
       [3]])

1
@sandroscodelller, вы смотрели на код, лежащий в основе vstack? np.concatenate([atleast_2d(_m) for _m in tup], 0), Он разбивает массив на (1,1) и объединяет их! В процессе это делает копию, в то время как все измененные вид делают представление.
hpaulj

3

Вы можете только транспонировать 2D-массив. Вы можете использовать numpy.matrixдля создания 2D-массива. Это на три года позже, но я просто добавляю к возможному набору решений:

import numpy as np
m = np.matrix([2, 3])
m.T

Использование np.matrixне требуется, и, как правило, не рекомендуется.
hpaulj



2

Другое решение .... :-)

import numpy as np

a = [1,2,4]

[1, 2, 4]

b = np.array([a]).T

массив ([[1], [2], [4]])


В чем проблема с этим решением ?!
омот

1

Я просто объединяю вышеупомянутый пост, надеюсь, это поможет другим сэкономить время:

Массив ниже имеет (2, )размерность, это 1-D массив,

b_new = np.array([2j, 3j])  

Есть два способа транспонировать одномерный массив:


нарежьте его с "np.newaxis" или без.

print(b_new[np.newaxis].T.shape)
print(b_new[None].T.shape)

Другой способ написания выше, без Tоперации.

print(b_new[:, np.newaxis].shape)
print(b_new[:, None].shape)

Обтекание [] или использование np.matrix означает добавление нового измерения.!

print(np.array([b_new]).T.shape)
print(np.matrix(b_new).T.shape)

0

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

np.transpose(a.reshape(len(a), 1))


0

Существует метод, не описанный в ответах, но описанный в документации к этому numpy.ndarray.transposeметоду:

Для одномерного массива это не имеет никакого эффекта, поскольку транспонированный вектор - это просто один и тот же вектор. Чтобы преобразовать одномерный массив в двухмерный вектор-столбец, необходимо добавить дополнительное измерение. np.atleast2d (a) .T достигает этого, как и [:, np.newaxis].

Можно сделать:

import numpy as np
a = np.array([5,4])
print(a)
print(np.atleast_2d(a).T)

Который (IMO) лучше, чем использовать newaxis.


0

По сути, функция транспонирования состоит в том, чтобы поменять местами форму и шаг массива:

>>> a = np.ones((1,2,3))

>>> a.shape
(1, 2, 3)

>>> a.T.shape
(3, 2, 1)

>>> a.strides
(48, 24, 8)

>>> a.T.strides
(8, 24, 48)

В случае одномерного массива 1D (массив ранга 1) форма и шаги являются кортежами из 1 элемента и не могут быть заменены, и транспонирование такого массива 1D возвращает его без изменений. Вместо этого вы можете (1, n)преобразовать «вектор- строку» (массив фигур ) в «вектор-столбец» (массив фигур (n, 1)). Чтобы достичь этого, вы должны сначала преобразовать свой массив 1D Numpy в вектор-строку, а затем поменять местами форму и шаг (переставить его). Ниже приведена функция, которая делает это:

from numpy.lib.stride_tricks import as_strided

def transpose(a):
    a = np.atleast_2d(a)
    return as_strided(a, shape=a.shape[::-1], strides=a.strides[::-1])

Пример:

>>> a = np.arange(3)
>>> a
array([0, 1, 2])

>>> transpose(a)
array([[0],
       [1],
       [2]])

>>> a = np.arange(1, 7).reshape(2,3)
>>> a     
array([[1, 2, 3],
       [4, 5, 6]])

>>> transpose(a)
array([[1, 4],
       [2, 5],
       [3, 6]])

Конечно, вам не нужно делать это таким образом, поскольку у вас есть одномерный массив, и вы можете напрямую преобразовать его в (n, 1)массив с помощью a.reshape((-1, 1))или a[:, None]. Я просто хотел продемонстрировать, как работает транспонирование массива.


0

Как я научился реализовывать это в компактной и удобочитаемой форме для 1-D массивов:

h = np.array([1,2,3,4,5])

v1 = np.vstack(h)
v2 = np.c_[h]

h1 = np.hstack(v1)
h2 = np.r_[v2[:,0]]

numpy.r_ и numpy.c_ переводят объекты среза в конкатенацию по первой и второй осям соответственно. Следовательно, разрезание v2 [:, 0] при перемещении обратно вертикального массива v2 в горизонтальный массив h2

numpy.vstack эквивалентен конкатенации вдоль первой оси после того, как одномерные массивы формы (N,) были преобразованы в (1, N). Восстанавливает массивы, разделенные на всплит .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.