2012-05-25 19 views
13

Jestem na mojej przejściowej podróży z MATLAB do scipy (+ numpy) + matplotlib. Wciąż mam problemy przy wdrażaniu niektórych rzeczy. Chcę utworzyć prostą tablicę wektorową w trzech różnych częściach. W MATLAB zrobiłbym coś takiego:tworzenie niewidocznych tablic z sekwencją

vector=[0.2,1:60,60.8]; 

Powoduje to jednowymiarową tablicę 62 pozycji. Próbuję wprowadzić to za pomocą scipy. Najbliżej jestem teraz to:

a=[[0.2],linspace(1,60,60),[60.8]] 

Jednak ten tworzy listę, a nie tablicy, a więc nie mogę przekształcić go do tablicy wektora. Ale potem, kiedy to zrobić, pojawia się błąd

a=array([[0.2],linspace(1,60,60),[60.8]]) 
ValueError: setting an array element with a sequence. 

wierzę mój Główną przeszkodą jest to, że nie mogę dowiedzieć się, jak przetłumaczyć tę prostą operację w programie MATLAB:

a=[1:2:20]; 

do NumPy . Wiem, jak to zrobić, aby uzyskać dostęp do pozycji w tablicy, ale nie podczas tworzenia sekwencji. Każda pomoc zostanie doceniona, dzięki!

Odpowiedz

13

A NumPy realizuje funkcję MATLAB macierzach tworzenie, wektor, wykorzystując dwa funkcji zamiast jednego - każdy domyślnie przyjmuje danej osi, wzdłuż której konkatenacja powinno się zdarzyć. Te funkcje to:

  • r_ (wiersz mądry konkatenacji) i

  • C_ (kolumna-wise)


Tak dla przykładu Odpowiednikiem NumPy jest:

>>> import numpy as NP 

>>> v = NP.r_[.2, 1:10, 60.8] 

>>> print(v) 
    [ 0.2 1. 2. 3. 4. 5. 6. 7. 8. 9. 60.8] 

Odpowiednikiem kolumna-wise to:

>>> NP.c_[.2, 1:10, 60.8] 

plaster notacja działa zgodnie z oczekiwaniami [start: przystanek: krok]:

>>> v = NP.r_[.2, 1:25:7, 60.8] 

>>> v 
    array([ 0.2, 1. , 8. , 15. , 22. , 60.8]) 

Choć jeśli Liczby urojone użyte jako trzeci argument, notacja krojenia zachowuje się jak linspace:

>>> v = NP.r_[.2, 1:25:7j, 60.8] 

>>> v 
    array([ 0.2, 1. , 5. , 9. , 13. , 17. , 21. , 25. , 60.8]) 


Inaczej zachowuje się jak arange:

>>> v = NP.r_[.2, 1:25:7, 60.8] 

>>> v 
    array([ 0.2, 1. , 8. , 15. , 22. , 60.8]) 
+0

dzięki Doug! To jest bardzo fajne, a to dwie postacie, które mają być tak kompaktowe jak Matlab. wspaniały! – lllllll

+0

@ vint-i-vuit bez problemu. Jeśli moja odpowiedź była dla ciebie pomocna, zaznacz ją jako "zaakceptowaną", klikając "znacznik wyboru" widoczny po kliknięciu myszą w wynik w lewym górnym rogu mojej odpowiedzi. (Lub jeśli inna odpowiedź była bardziej pomocna, oczywiście będziesz chciał zaznaczyć ten jeden). Tak, to jeszcze dwie postacie, ale myślę, że warto, aby NumPy mógł mieć jedną funkcję dla każdej z dwóch osi, aby się połączyć (r_ i c_). – doug

+0

nie wiedziałem o tym, tak!Wiele się nauczyłem ze wszystkich stanowisk, wszystkie działają tak, jak chciałem, ale prawdopodobnie twój jest najbliższy MATLAB-owi. dziękuje za wszystko! – lllllll

5

Można spróbować czegoś takiego:

a = np.hstack(([0.2],np.linspace(1,60,60),[60.8])) 
+0

prawda! to też działa, dzięki JoshAdel. Czy jest to jedyna opcja, gdy chcę zrobić coś takiego jak a = [1: 2: 20]? Co oznacza, że ​​nie wiem, ostateczny rozmiar wektora, tylko krok i punkt początkowy/końcowy. [bis] – lllllll

+1

Po prostu znalazłem to sam dzięki mgilson. Odpowiedzią jest zasięg (start, stop, krok). wspaniały! – lllllll

+0

@ vint-i-vuit Zwróć uwagę, że wbudowana funkcja pasma Pythona działa tylko dla wartości całkowitych. Numpy dostarcza 'arange', który zrobi to samo (również z pływającymi, jeśli chcesz) zwracając tablicę, ale dokumentacja stwierdza, że' linspace' jest lepszą opcją w większości przypadków, ponieważ (z powodu zaokrąglenia), wyniki z 'arange' może nie być dokładnie tym, czego oczekujesz. – mgilson

1

jeśli rozumiem MATLAB poprawnie, można osiągnąć coś takiego za pomocą:

a=np.array([0.2]+list(range(1,61))+[60.8]) 

Ale nie ma chyba lepszego sposobu na ... list(range(1,61)) może po prostu być range(1,61), jeśli używasz Pythona 2.X.

Umożliwia to utworzenie 3 list, a następnie łączenie ich za pomocą operatora +.

Powodem oryginalna próba nie działa dlatego

a=[ [0.2], np.linspace(1,60,60), [60.8] ] tworzy listę list - innymi słowy:

a[0] == [0.2] #another list (length 1) 
a[1] == np.linspace(1,60,60) #an array (length 60) 
a[2] == [60.8] #another list (length 1) 

Funkcja array oczekuje iterowalny że jest sekwencja, lub sekwencja sekwencji o tej samej długości.

+0

super mgilson! to prawdopodobnie najbliższy składni MATLAB. Nadal nie jest tak kompaktowy jak a = [0.2.1: 6060,8], ale fajny. dziękuję bardzo, teraz widzę to wyraźniej. – lllllll

+0

Myślę, że przekonasz się, że podczas gdy wiele rzeczy w 'numpy' są tak samo zwięzłe jak w matlab (i kilka rzeczy nieco bardziej zwięzłych), istnieje sporo rzeczy, które nie są tak zwięzłe - jednak Ogólnie uważam, że kod jest znacznie bardziej intuicyjny. – mgilson

+0

Warto wiedzieć, że elastyczność nabyta, szczególnie przy kreśleniu, jest tak niezwykle warta "mniejszej zwięzłości" składni, jak dotąd. :) – lllllll

3
np.concatenate([[.2], linspace(1,60,60), [60.8]]) 
+0

cholera, prawda! to działa, dzięki larsmans. Czy jest to jedyna opcja, gdy chcę zrobić coś takiego jak a = [1: 2: 20]? Co oznacza, że ​​nie wiem, ostateczny rozmiar wektora, tylko krok i punkt początkowy/końcowy. – lllllll

+1

Właśnie znalazłem to dzięki mgilson. Answe to range (start, stop, step). wspaniały! – lllllll

+1

Możesz również wypróbować 'np.arange (1,20,2)' chociaż bądź ostrożny, ponieważ ta operacja nie zawiera ostatniej liczby w zakresie (np. Tablica ([1, 3, 5, 7, 9, 11, 13, 15, 17, 19])). Zapominam, jak Matlab sobie z tym radzi i już dawno usunąłem to z mojej maszyny. – JoshAdel

2

jakoś podoba mi się pomysł skonstruowania tych segmentacji zakresy pan wspomniał. Jeśli używasz ich dużo, może mały funkcja jak

import numpy as np 

def segrange(*args): 
    result = [] 
    for arg in args: 
     if hasattr(arg,'__iter__'): 
      result.append(range(*arg)) 
     else: 
      result.append([arg]) 
    return np.concatenate(result) 

który daje

>>> segrange(1., (2,5), (5,10,2)) 
[ 1. 2. 3. 4. 5. 7. 9.] 

byłoby miło mieć. Chociaż prawdopodobnie wybrałbym odpowiedź używając konkatenacji/hstack.

+0

To miła myśl! Myślę, że postaram się trzymać operatora '+' używanego w odpowiedzi od użytkownika mgilsona, ponieważ to ten, który znajduję się najbliżej matlab, stąd mniej wysiłku pamiętając. Jednak zobaczę, czy wykonanie tego kodu jest wygodniejsze w niektórych przypadkach :) – lllllll

+1

Popraw mnie, jeśli się mylę, ale myślę, że 'isinstance (arg, list)' jest preferowany zamiast 'type (arg) is list'. Możesz także skrócić ten cały blok if do 'hasattr (arg, '__ iter __')' (i przechwycić wszystkie inne iterables podczas gdy jesteś w tym) – mgilson

+0

yep, twoja prawa mgilson. ale odpowiedź douga przynosi _r zastępuje wszystko ^^ – pwuertz

1

Spójrz na np.r_.Jest to w zasadzie odpowiednik tego, co wszyscy sugerowali, ale jeśli przychodzisz z Matlaba, jest to trochę bardziej intuicyjne (a jeśli pochodzisz z jakiegokolwiek innego języka, jest to trochę sprzeczne z intuicją).

Przykładowo vector=[0.2,1:60,60.8]; przekłada się na:

vector = np.r_[0.2, 1:61, 60.8] 
1

prostu chcą zwrócić uwagę na innych ludzi, począwszy od MATLAB do NumPy że można skonstruować tablicę np.r_ z dwukropkami, a następnie użyj jej do indeksu

Np. jeśli masz w Matlab

arr_ones = ones(10,10) 

Albo w NumPy

arr_ones = np.ones([10,10]) 

Można w Matlab podjąć tylko kolumny od 1 do 5 oraz 7 tak:

arr_ones(:,[1:5 7]) 

robi to samo w NumPy nie jest (przynajmniej dla mnie) intuicyjny. To daje „nieważne składni” Błąd:

arr_ones[:,[1:5,7]] 

Jednak to działa:

inds = np.r[1:5,] 
arr_ones[:,inds] 

wiem, że to nie jest technicznie nowa odpowiedź, ale przy użyciu dwukropka skonstruować tablicę podczas indeksowania na matrycę wydaje się tak naturalna w Matlab, założę się, że wiele osób, które przyjdą na tę stronę, będzie chciało to wiedzieć. (Przyszedłem tutaj, zamiast zadawać nowe pytanie.)

Powiązane problemy