Chcę wyciąć tablicę NumPy nxn. Chcę wyodrębnić plik dowolny wybór m wierszy i kolumn tej tablicy (tj. Bez żadnego wzorca w liczbie wierszy / kolumn), tworząc nową tablicę mxm. W tym przykładzie powiedzmy, że tablica to 4x4 i chcę wyodrębnić z niej tablicę 2x2.
Oto nasza tablica:
from numpy import *
x = range(16)
x = reshape(x,(4,4))
print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
Linia i kolumny do usunięcia są takie same. Najłatwiej jest wtedy, gdy chcę wyodrębnić podmacierz 2x2, która jest na początku lub na końcu, czyli:
In [33]: x[0:2,0:2]
Out[33]:
array([[0, 1],
[4, 5]])
In [34]: x[2:,2:]
Out[34]:
array([[10, 11],
[14, 15]])
Ale co, jeśli muszę usunąć inną kombinację wierszy / kolumn? Co się stanie, jeśli muszę usunąć pierwszą i trzecią linię / wiersz, wyodrębniając w ten sposób podmacierz [[5,7],[13,15]]
? Może istnieć dowolna kompozycja wierszy / linii. Czytałem gdzieś, że muszę po prostu zindeksować moją tablicę za pomocą tablic / list indeksów zarówno dla wierszy, jak i kolumn, ale to nie działa:
In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])
Znalazłem jeden sposób, czyli:
In [61]: x[[1,3]][:,[1,3]]
Out[61]:
array([[ 5, 7],
[13, 15]])
Po pierwsze, jest to trudne do odczytania, chociaż mogę z tym żyć. Jeśli ktoś ma lepsze rozwiązanie, z pewnością bym to usłyszał.
Inną rzeczą, którą przeczytałem na forum, jest to, że indeksowanie tablic za pomocą tablic zmusza NumPy do wykonania kopii żądanej tablicy, więc podczas traktowania z dużymi tablicami może to stać się problemem. Dlaczego tak jest / jak działa ten mechanizm?
x[[[1],[3]],[1,3]]
tworzy tylko jedną nową tablicę, podczas gdyx[[1,3],:][:,[1,3]]
kopiuje dwukrotnie, więc użyj pierwszej.Nie sądzę, żeby
x[[1,3]][:,[1,3]]
było to trudne do odczytania. Jeśli chcesz mieć większą jasność co do swoich zamiarów, możesz:Nie jestem ekspertem w krojeniu, ale zazwyczaj, jeśli spróbujesz wyciąć tablicę, a wartości są ciągłe, otrzymasz widok, w którym wartość kroku zostanie zmieniona.
np. w twoich wejściach 33 i 34, mimo że otrzymujesz tablicę 2x2, krok wynosi 4. Tak więc, kiedy indeksujesz następny wiersz, wskaźnik przesuwa się na właściwą pozycję w pamięci.
Oczywiście ten mechanizm nie działa dobrze w przypadku tablicy indeksów. Dlatego numpy będzie musiał wykonać kopię. W końcu wiele innych funkcji matematycznych opiera się na rozmiarze, kroku i ciągłej alokacji pamięci.
źródło
Jeśli chcesz pominąć co drugi wiersz i co drugą kolumnę, możesz to zrobić za pomocą podstawowego krojenia:
Zwraca widok, a nie kopię twojej tablicy.
while
z=x[(1,3),:][:,(1,3)]
używa zaawansowanego indeksowania i dlatego zwraca kopię:Zauważ, że
x
to się nie zmieniło:Jeśli chcesz wybrać dowolne wiersze i kolumny, nie możesz użyć podstawowego cięcia. Będziesz musiał użyć zaawansowanego indeksowania, używając czegoś takiego jak sekwencje
x[rows,:][:,columns]
, gdzierows
icolumns
są. To oczywiście da ci kopię, a nie widok oryginalnej tablicy. Jest to zgodne z oczekiwaniami, ponieważ tablica numpy używa ciągłej pamięci (ze stałymi krokami) i nie byłoby sposobu na wygenerowanie widoku z dowolnymi wierszami i kolumnami (ponieważ wymagałoby to niestałych kroków).źródło
Za pomocą numpy możesz przekazać wycinek dla każdego składnika indeksu - więc twój
x[0:2,0:2]
przykład powyżej działa.Jeśli chcesz po prostu równomiernie pomijać kolumny lub wiersze, możesz przekazać plasterki z trzema komponentami (tj. Start, stop, step).
Ponownie, dla twojego przykładu powyżej:
To jest w zasadzie: wycinek w pierwszym wymiarze, zaczynając od indeksu 1, zatrzymuj się, gdy indeks jest równy lub większy niż 4 i dodawaj 2 do indeksu w każdym przejściu. To samo dotyczy drugiego wymiaru. Ponownie: działa to tylko dla stałych kroków.
Składnia, którą musisz zrobić wewnętrznie coś zupełnie innego - co
x[[1,3]][:,[1,3]]
faktycznie robi, to utworzenie nowej tablicy zawierającej tylko wiersze 1 i 3 z oryginalnej tablicy (zrobione zx[[1,3]]
częścią), a następnie ponowne podzielenie jej - tworząc trzecią tablicę - zawierającą tylko kolumny 1 i 3 poprzedniej tablicy.źródło
Mam tutaj podobne pytanie: Pisanie w sub-ndarray z ndarray w najbardziej pytoński sposób. Python 2 .
Zgodnie z rozwiązaniem z poprzedniego postu dla Twojej sprawy rozwiązanie wygląda następująco:
Korzystanie ix_:
Który jest:
źródło
Nie jestem pewien, jak wydajne jest to, ale możesz użyć range (), aby wyciąć w obu osiach
źródło