2013-07-02 19 views
29

Czy istnieje dobry sposób na rozróżnianie wektorów wiersza i kolumny w python? Do tej pory używam numpy i scipy i co widzę tak daleko, że jeśli miałem dać jeden wektor, powiedzmyPython: Rozróżnianie wektorów wiersza i kolumny

from numpy import * 
Vector = array([1,2,3]) 

nie byłby w stanie powiedzieć pogoda Znaczy wiersza lub kolumny wektor. Ponadto:

array([1,2,3]) == array([1,2,3]).transpose() 
True 

Co w "prawdziwym świecie" jest po prostu nieprawdą. Zdaję sobie sprawę, że większość funkcji na wektorach z wymienionych modułów nie wymaga rozróżnienia. Na przykład outer(a,b) lub a.dot(b), ale chciałbym wyróżnić dla własnej wygody.

+3

Zachowanie który obserwujemy jest faktycznie * poprawna * „w realnym świecie ": * jedna * wymiarowa sekwencja liczb nie jest ani rzędem, ani kolumnowym wektorem. Wektor wiersza lub kolumny jest w rzeczywistości * dwuwymiarową tablicą (w której jeden z dwóch wymiarów to 1). Zatem twoje testy powinny być wykonywane za pomocą 'array ([[1, 2, 3]]), która nie jest równa jej transpozycji. – EOL

+0

To jest matematycznie nie do końca poprawne. Matryce to mxn, a wektory rzędów są z definicji tymi, w których m = 1, a wektorami kolumnowymi są te, w których n = 1. Wymiarowość jest zupełnie inna w matematyce, ma do czynienia z liczbą wektorów w podstawie ustalonej w przestrzeni wektorowej, więc tak naprawdę nie powinniśmy w ogóle mówić o wymiarowości pojedynczego wektora. Myślę, że oryginalny plakat w rozmowach o "realnym świecie" mówił o świecie algebry liniowej i matematyki, więc był poprawny. Programiści zwykle używają niewłaściwych terminów. – neuronet

Odpowiedz

39

Rozróżnienie można wyrazić, dodając kolejny wymiar do tablicy.

>>> a = np.array([1, 2, 3]) 
>>> a 
array([1, 2, 3]) 
>>> a.transpose() 
array([1, 2, 3]) 
>>> a.dot(a.transpose()) 
14 

teraz zmusić go do być wektorem kolumna:

>>> a.shape = (3,1) 
>>> a 
array([[1], 
     [2], 
     [3]]) 
>>> a.transpose() 
array([[1, 2, 3]]) 
>>> a.dot(a.transpose()) 
array([[1, 2, 3], 
     [2, 4, 6], 
     [3, 6, 9]]) 

Inną opcją jest użycie np.newaxis gdy chcesz wprowadzić rozróżnienie:

>>> a = np.array([1, 2, 3]) 
>>> a 
array([1, 2, 3]) 
>>> a[:, np.newaxis] 
array([[1], 
     [2], 
     [3]]) 
>>> a[np.newaxis, :] 
array([[1, 2, 3]]) 
+0

Myślałem o tym, ale to oznacza, że ​​__getitem__ staje się niespójne: 'a [0] = [1]', 'a [0] [0] = 1' dla wektora kolumny i' a [0] = 1', ' a [0] [0] = TypeError' dla wektora wiersza. – MarcinKonowalczyk

+2

Tak, to kompromis, który musisz wziąć pod uwagę. Inną opcją jest użycie np.newaxis, gdy musisz dokonać rozróżnienia (patrz edycja do mojej odpowiedzi). – bogatron

+0

Inny sposób przekształcania wektora wiersza (tablica 1d) w wektor kolumnowy (zwraca kopię): 'a.reshape (a.size, 1)', a nawet 'a.reshape (-1, 1)' jeśli jesteś leniwy me –

1

Wygląda Python Numpy nie odróżnia go chyba go użyć w kontekście: „Można mieć standardowych wektorów lub wektory wiersz/kolumna jeśli lubisz”

":) Można traktuj tablice 1-sza jako wektory wierszowe lub kolumnowe, kropka (A, v) traktuje v jako wektor kolumnowy, a kropka (v, A) traktuje v jako wektor wierszy, co może zaoszczędzić na konieczności wpisania wielu transpozycji . "

Co więcej, specyficzny dla Twojego kodu:" Transpozycja na macierzy rank-1 nic nie robi. " Źródło: http://wiki.scipy.org/NumPy_for_Matlab_Users

+0

Wiem o tym. Chcę sposób ich odróżnić. Może jakiś inny moduł matematyki? – MarcinKonowalczyk

3

Jeśli chcesz w tej sprawie zalecam użycie zamiast tego matrix, gdzie:

matrix([1,2,3]) == matrix([1,2,3]).transpose() 

daje:

matrix([[ True, False, False], 
     [False, True, False], 
     [False, False, True]], dtype=bool) 

Można również użyć ndarray wyraźnie dodając drugi wymiar:

array([1,2,3])[None,:] 
#array([[1, 2, 3]]) 

oraz:

array([1,2,3])[:,None] 
#array([[1], 
#  [2], 
#  [3]]) 
+0

'tablica ([1,2,3]) [Brak,:]' jest znacznie bardziej skomplikowana niż jawna 'tablica ([[1, 2, 3]])'. – EOL

+2

'matryca' jest generalnie warta uniknięcia, ponieważ nie generalizuje do wyższych wymiarów – Eric

0

Doskonała Pandas biblioteka dodaje funkcje do numpy, które sprawiają, tego rodzaju operacje są bardziej intuicyjne IMO. Na przykład:

import numpy as np 
import pandas as pd 

# column 
df = pd.DataFrame([1,2,3]) 

# row 
df2 = pd.DataFrame([[1,2,3]]) 

Możesz nawet define a DataFrame and make a spreadsheet-like pivot table.

+2

Ponieważ możesz napisać to samo w NumPy, dodałbym ważny fakt, że zarówno 'df [0] = 10' jak i' df2 [0 ] = 10 działa zgodnie z oczekiwaniami, gdy myślimy o wektorach wierszowych i kolumnowych. W tym miejscu Panda jest wygodna w porównaniu do NumPy. – EOL

1

Myślę, że możesz użyć opcji ndmin z numpy.array. Utrzymanie go na poziomie 2 oznacza, że ​​będzie to (4,1), a transpozycja będzie wynosić (1,4).

>>> a = np.array([12, 3, 4, 5], ndmin=2) 
>>> print a.shape 
>>> (1,4) 
>>> print a.T.shape 
>>> (4,1) 
0

Kiedy próbowałem obliczyć w^T * x użyciu numpy, było również bardzo mylące dla mnie. W rzeczywistości nie mogłem sam tego wdrożyć. Jest to jeden z niewielu gier w NumPy, z którymi musimy się zapoznać.

ile 1D Tablica się, to nie ma żadnej różnicy pomiędzy wektora wierszy i kolumn wektora. Są dokładnie takie same.

Spójrz na poniższe przykłady, w których możemy uzyskać ten sam rezultat w każdym przypadku, co nie jest prawdą w (teoretyczne poczucie) algebry liniowej:

In [37]: w 
Out[37]: array([0, 1, 2, 3, 4]) 

In [38]: x 
Out[38]: array([1, 2, 3, 4, 5]) 

In [39]: np.dot(w, x) 
Out[39]: 40 

In [40]: np.dot(w.transpose(), x) 
Out[40]: 40 

In [41]: np.dot(w.transpose(), x.transpose()) 
Out[41]: 40 

In [42]: np.dot(w, x.transpose()) 
Out[42]: 40 

Dzięki tej informacji, teraz spróbujmy obliczyć kwadratową długość wektora |w|^2.

W tym celu musimy przekształcić w na tablicę 2D.

In [51]: wt = w[:, np.newaxis] 

In [52]: wt 
Out[52]: 
array([[0], 
     [1], 
     [2], 
     [3], 
     [4]]) 

Teraz Obliczmy długość kwadratu (lub kwadratu wielkości) wektora w:

In [53]: np.dot(w, wt) 
Out[53]: array([30]) 

Zauważ, że użyliśmy w, wt zamiast wt, w (jak w teoretycznym algebry liniowej) z powodu niedopasowania kształtu za pomocą np.dot (wt, w). Mamy więc kwadratową długość wektora jako [30]. Może to jeden ze sposobów odróżnienia (numpy's interpretacja) wektora wiersza i kolumny?

I wreszcie, czy wspomniałem, że wymyśliłem sposób na wdrożenie w^T * x? Tak, zrobiłem:

In [58]: wt 
Out[58]: 
array([[0], 
     [1], 
     [2], 
     [3], 
     [4]]) 

In [59]: x 
Out[59]: array([1, 2, 3, 4, 5]) 

In [60]: np.dot(x, wt) 
Out[60]: array([40]) 

Więc w NumPy kolejność argumentów jest odwracany, co widać powyżej, wbrew temu, co badaliśmy w teoretycznym algebry liniowej.


P.S.: potential gotchas in numpy

+0

jeśli spróbujesz zrobić 'np.hstack' lub' np.vstack' na liście tablic 1-D, to naprawdę robi różnicę! Jeśli każda z tablic ma kształt '(10,)', wyniki dla 'hstack' to' (20,) 'a dla' vstack' to '(2, 10)'. Oznacza to, że są to wektory kolumnowe! –

0

Oto kolejny intuicyjny sposób. Załóżmy, że mamy:

>>> a = np.array([1, 3, 4]) 
>>> a 
array([1, 3, 4]) 

Najpierw tworzymy tablicę 2D z tym jako jedyny rząd:

>>> a = np.array([a]) 
>>> a 
array([[1, 3, 4]]) 

Wtedy możemy go transpozycji:

>>> a.T 
array([[1], 
     [3], 
     [4]]) 
6

używać podwójnego [] podczas pisania wektory.

Następnie, jeśli chcesz wektor rzędu:

row_vector = array([[1, 2, 3]]) # shape (1, 3) 

Albo jeśli chcesz wektor kolumna:

col_vector = array([[1, 2, 3]]).T # shape (3, 1) 
Powiązane problemy