Транспонування масиву NumPy


193

Я використовую Python і NumPy і у мене є проблеми з "транспонировать":

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

Викликання a.Tне переносить масив. Якщо aце, наприклад, [[],[]]тоді він транспонірується правильно, але мені потрібно транспонування [...,...,...].


також спробував "надрукувати a.transpose", що те саме, але без успіху, не переносити ...
Thaking

Відповіді:


247

Працює саме так, як і належить. Транспонування 1D масиву все ще є 1D масивом! (Якщо ви звикли до matlab, він принципово не має поняття 1D масиву. "1D" масиви Matlab - це 2D.)

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

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

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


2
@thaking - я просто використовував np.arangeдля швидкого створення 1D масиву. Це працює точно так само для 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 масиву корисно. Обчислення відстані між усіма 1D точками у масиві. Завдяки вашому рішенню можна зробити x - x [np.newaxis] .T, який дає матрицю відстані
JuanPi

4
Особисто я вважаю , np.vstack()робота буде більш явним: print np.vstack(a).
Олександр Позднеєв

2
Це не просто матлаб, а лінійна алгебра має концепцію вектора рядків / стовпців. Нумпі є ідіосинкратичним для людей, які приїжджають з багатьох місць, а не лише з матлаба.
eric

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

Для масивів 1D :

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
Дякуємо за ваше зауваження. Я бачу вашу думку, але я вважаю, що це відволікає більше, ніж очищає мою відповідь, тому що я даю просте однолінійне рішення точного питання, яке @hamking кадри. Йдеться не про 2-d масиви, це про 1-d масиви. Яблука та груші тут.
Ульф Аслак

2
Звичайно. Ваша відповідь правильна і елегантна для цього випадку, я ніколи не мав намір її критикувати. Але, з огляду на назву питання ("Транспонування масиву NumPy"), я підозрюю, що багато відвідувачів приїдуть сюди шукають більш загальне рішення, і я хотів попередити їх, що він не застосовується до 2D-масивів. Інакше ваша відповідь правильна і відповідна, враховуючи питання ОП.
johndodo

@UlfAslak, будь ласка, оновіть свою відповідь, що ваш підхід не є узагальнюючим для ND-масиву, завжди добре бути чітким, як це запропонував! Johndodo, щоб ніхто не використовував вашу техніку неправильно.!, Питання тут - для правильної відповіді & не лайнер.!
Ану

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

numpy 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]])


У чому проблема цього рішення ?!
omotto

1

Я просто консолідую вищезгаданий пост, сподіваюся, що це допоможе іншим заощадити час:

Нижній масив має (2, )розмірність, це 1-D масив,

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

Є два способи переміщення 1-D масиву:


нарізати його "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методу:

Для 1-D масиву це не має ефекту, оскільки транспонований вектор - це просто той самий вектор. Щоб перетворити 1-D масив у векторний двовимірний стовпець, слід додати додатковий вимір. 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 масивного масиву (масив ran-1) форма і кроки є одноелементними кортежами і їх не можна міняти, а транспонування такого 1D масиву повертає його незмінним. Натомість можна перенести "рядок-вектор" (numpy масив фігури (1, n)) у "колонку-вектор" (numpy масив фігури (n, 1)). Для цього вам потрібно спершу перетворити свій 1D масив нумерів у векторний рядок, а потім поміняти форму та кроки (перекласти його). Нижче наведена функція, яка виконує це:

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]])

Звичайно, вам не потрібно робити це так, оскільки у вас є 1D масив, і ви можете безпосередньо переробити його в (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 еквівалентний конкатенації вздовж першої осі після того, як 1-D масиви форми (N,) були перероблені до (1, N). Перебудовує масиви, розділені на vsplit .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.