Jaki jest cel działania siatki w Pythonie / NumPy?

302

Czy ktoś może mi wyjaśnić, jaki jest cel meshgriddziałania Numpy? Wiem, że tworzy ona pewnego rodzaju siatkę współrzędnych do kreślenia, ale tak naprawdę nie widzę bezpośrednich korzyści z tego.

Uczę się „uczenia maszynowego w języku Python” od Sebastiana Raschki i używa go do kreślenia granic decyzji. Zobacz wejście 11 tutaj .

Próbowałem również tego kodu z oficjalnej dokumentacji, ale znowu, wyniki naprawdę nie mają dla mnie sensu.

x = np.arange(-5, 5, 1)
y = np.arange(-5, 5, 1)
xx, yy = np.meshgrid(x, y, sparse=True)
z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
h = plt.contourf(x,y,z)

Proszę, jeśli to możliwe, pokaż mi także wiele przykładów z prawdziwego świata.

HonzaB
źródło

Odpowiedzi:

388

Celem meshgridjest utworzenie prostokątnej siatki z tablicy wartości x i tablicy wartości y.

Na przykład, jeśli chcemy utworzyć siatkę, w której mamy punkt przy każdej wartości całkowitej od 0 do 4 w obu kierunkach xiy. Aby utworzyć prostokątną siatkę, potrzebujemy każdej kombinacji punktów xi y.

To będzie 25 punktów, prawda? Więc jeśli chcielibyśmy stworzyć tablicę xiy dla wszystkich tych punktów, moglibyśmy wykonać następujące czynności.

x[0,0] = 0    y[0,0] = 0
x[0,1] = 1    y[0,1] = 0
x[0,2] = 2    y[0,2] = 0
x[0,3] = 3    y[0,3] = 0
x[0,4] = 4    y[0,4] = 0
x[1,0] = 0    y[1,0] = 1
x[1,1] = 1    y[1,1] = 1
...
x[4,3] = 3    y[4,3] = 4
x[4,4] = 4    y[4,4] = 4

Spowodowałoby to następujące xi ymacierze, tak że parowanie odpowiedniego elementu w każdej macierzy daje współrzędne xiy punktu w siatce.

x =   0 1 2 3 4        y =   0 0 0 0 0
      0 1 2 3 4              1 1 1 1 1
      0 1 2 3 4              2 2 2 2 2
      0 1 2 3 4              3 3 3 3 3
      0 1 2 3 4              4 4 4 4 4

Następnie możemy wykreślić je, aby sprawdzić, czy są siatką:

plt.plot(x,y, marker='.', color='k', linestyle='none')

wprowadź opis zdjęcia tutaj

Oczywiście staje się to bardzo nudne, szczególnie w przypadku dużych zakresów xi y. Zamiast tego meshgridmoże faktycznie wygenerować to dla nas: wszystko, co musimy określić, to unikalność xi ywartości.

xvalues = np.array([0, 1, 2, 3, 4]);
yvalues = np.array([0, 1, 2, 3, 4]);

Teraz, kiedy dzwonimy meshgrid, automatycznie uzyskujemy poprzedni wynik.

xx, yy = np.meshgrid(xvalues, yvalues)

plt.plot(xx, yy, marker='.', color='k', linestyle='none')

wprowadź opis zdjęcia tutaj

Tworzenie tych prostokątnych siatek jest przydatne do wielu zadań. W przykładzie podanym w poście jest to po prostu sposób na przetestowanie funkcji ( sin(x**2 + y**2) / (x**2 + y**2)) w zakresie wartości dla xi y.

Ponieważ próbkę tę próbkowano na prostokątnej siatce, można ją teraz wizualizować jako „obraz”.

wprowadź opis zdjęcia tutaj

Dodatkowo wynik można teraz przekazać do funkcji oczekujących danych na siatce prostokątnej (tj. contourf)

Suever
źródło
10
Nie wyjaśniłeś wartości zwracanych xxi yy. Tajemnicze dla mnie było to, dlaczego zwraca tę parę wyników i jak wyglądają. Odpowiedź Hai Phana jest do tego przydatna. Myślę, że robi to dla wygody, ponieważ fabuła chce dwóch takich parametrów.
nealmcb
2
Nie wiem - dlatego szukam tych informacji;) Nie twierdzę więc, że powinien zwrócić coś innego. Po prostu staram się zgadywać brakującą informację dla tych, którzy właśnie przeczytali zaakceptowaną odpowiedź. A jeśli chcesz, sugeruję, że twoja odpowiedź (która jest już bardzo miła - dziękuję!) Byłaby nieco bardziej kompletna, gdybyś wyjaśnił wartości zwracane (tak jak Hai), dla tych z nas, którzy są nadal zdziwieni.
nealmcb
1
Aby lepiej zrozumieć wartości xx i yy, rozważ twierdzenie, że poniższy kod daje ci ten sam wynik, co np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Matt Kleinsmith
1
Ta odpowiedź jest myląca - czy nie jest to twoja pierwsza ilustracja xi ywstecz? Kiedy to zrobisz xx, yy = np.meshgrid(np.arange(4), np.arange(4)), jest to odwrotność tego, co masz xi yw pierwszej części odpowiedzi. Dopasowuje kolejność danych wyjściowych dla mgrid, ale nie siatki. xxNależy wzrasta w kierunku x, ale yours zwiększa się w kierunku y.
Scott Staniewicz
1
@ScottStaniewicz Dziękuję za wskazanie, że nasz, teraz pewien, jak to pomieszałem ... Zaktualizowano!
Suever
249

Dzięki uprzejmości Microsoft Excel: 

wprowadź opis zdjęcia tutaj

Sarsaparilla
źródło
6
Miły. Fwiw, jeśli chcesz macierz 2 x 12 par pośrodku:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
denis
5
a jeśli chcesz macierz 12 x 2 par pośrodku:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn
2
Niezła odpowiedź. Celem siatki siatki jest utworzenie siatki przy użyciu współrzędnych każdego przyciemnienia.
Dobry chłopiec
1
To, co wydaje mi się trochę dziwne, to to, że wartości xiy są zwracane osobno, zamiast już połączone w jedną tablicę. Jeśli chcę je w jednej tablicy, muszę zrobić:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892
64

W rzeczywistości cel np.meshgridjest już wspomniany w dokumentacji:

np.meshgrid

Zwraca macierze współrzędnych z wektorów współrzędnych.

Twórz tablice współrzędnych ND dla wektoryzowanych ocen pól skalarnych / wektorowych ND na siatkach ND, biorąc pod uwagę jednowymiarowe tablice współrzędnych x1, x2, ..., xn.

Więc głównym celem jest utworzenie macierzy współrzędnych.

Prawdopodobnie po prostu zadałeś sobie pytanie:

Dlaczego musimy tworzyć macierze współrzędnych?

Powodem, dla którego potrzebujesz macierzy współrzędnych w Pythonie / NumPy, jest brak bezpośredniej relacji między współrzędnymi a wartościami, z wyjątkiem sytuacji, gdy współrzędne zaczynają się od zera i są czysto dodatnimi liczbami całkowitymi. Następnie możesz po prostu użyć indeksów tablicy jako indeksu. Jednak gdy tak nie jest, musisz jakoś przechowywać współrzędne obok swoich danych. Tam właśnie wchodzą siatki.

Załóżmy, że Twoje dane to:

1  2  1
2  5  2
1  2  1

Każda wartość reprezentuje jednak obszar o szerokości 2 kilometrów w poziomie i 3 kilometry w pionie. Załóżmy, że twoim początkiem jest lewy górny róg i potrzebujesz tablic reprezentujących odległość, którą możesz użyć:

import numpy as np
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)

gdzie v jest:

array([[0, 0, 0],
       [2, 2, 2],
       [4, 4, 4]])

i H:

array([[0, 3, 6],
       [0, 3, 6],
       [0, 3, 6]])

Więc jeśli masz dwa wskaźniki, powiedzmy xi y(dlatego wartość zwracana meshgridjest zwykle xxlub xszamiast xw tym przypadku wybrałem hpoziomo!), Możesz uzyskać współrzędną x punktu, współrzędną y punktu i wartość w tym punkcie przy użyciu:

h[x, y]    # horizontal coordinate
v[x, y]    # vertical coordinate
data[x, y]  # value

To znacznie ułatwia śledzenie współrzędnych i (co ważniejsze) można przekazać je do funkcji, które muszą znać współrzędne.

Nieco dłuższe wyjaśnienie

Jednak np.meshgridsam nie jest często używany bezpośrednio, głównie używa się jednego z podobnych obiektów np.mgridlub np.ogrid. Tutaj np.mgridreprezentuje sparse=Falsei np.ogridten sparse=Trueprzypadek (odnoszę się do sparseargumentu np.meshgrid). Należy pamiętać, że istnieje znaczna różnica między np.meshgridi np.ogrida np.mgrid: Pierwsze dwie zwracane wartości (jeśli są dwa lub więcej) są odwrócone. Często nie ma to znaczenia, ale powinieneś podać sensowne nazwy zmiennych w zależności od kontekstu.

Na przykład w przypadku siatki 2D matplotlib.pyplot.imshowsensowne jest nazwanie pierwszego zwróconego elementu np.meshgrid xi drugiego, ygdy jest odwrotnie dla np.mgridi np.ogrid.

np.ogrid i rzadkie siatki

>>> import numpy as np
>>> yy, xx = np.ogrid[-5:6, -5:6]
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5],
       [-4],
       [-3],
       [-2],
       [-1],
       [ 0],
       [ 1],
       [ 2],
       [ 3],
       [ 4],
       [ 5]])

Jak już powiedziano, wynik jest odwrócony w porównaniu do np.meshgrid, dlatego rozpakowałem go jako yy, xxzamiast xx, yy:

>>> xx, yy = np.meshgrid(np.arange(-5, 6), np.arange(-5, 6), sparse=True)
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5],
       [-4],
       [-3],
       [-2],
       [-1],
       [ 0],
       [ 1],
       [ 2],
       [ 3],
       [ 4],
       [ 5]])

To już wygląda jak współrzędne, szczególnie linie xiy dla wykresów 2D.

Wizualizowane:

yy, xx = np.ogrid[-5:6, -5:6]
plt.figure()
plt.title('ogrid (sparse meshgrid)')
plt.grid()
plt.xticks(xx.ravel())
plt.yticks(yy.ravel())
plt.scatter(xx, np.zeros_like(xx), color="blue", marker="*")
plt.scatter(np.zeros_like(yy), yy, color="red", marker="x")

wprowadź opis zdjęcia tutaj

np.mgrid i gęste / rozwinięte siatki

>>> yy, xx = np.mgrid[-5:6, -5:6]
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
       [-4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4],
       [-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2],
       [ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3],
       [ 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4],
       [ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5]])

To samo dotyczy tutaj: Wyjście jest odwrócone w porównaniu do np.meshgrid:

>>> xx, yy = np.meshgrid(np.arange(-5, 6), np.arange(-5, 6))
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
       [-4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4],
       [-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2],
       [ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3],
       [ 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4],
       [ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5]])

W przeciwieństwie do ogridtych tablic zawierają wszystkie xx i yywspółrzędne w -5 <= xx <= 5; -5 <= yy <= 5 siatki.

yy, xx = np.mgrid[-5:6, -5:6]
plt.figure()
plt.title('mgrid (dense meshgrid)')
plt.grid()
plt.xticks(xx[0])
plt.yticks(yy[:, 0])
plt.scatter(xx, yy, color="red", marker="x")

wprowadź opis zdjęcia tutaj

Funkcjonalność

Te funkcje nie ograniczają się tylko do 2D, te funkcje działają dla dowolnych wymiarów (cóż, maksymalna liczba argumentów podanych do działania w Pythonie i maksymalna liczba wymiarów dozwolona przez NumPy):

>>> x1, x2, x3, x4 = np.ogrid[:3, 1:4, 2:5, 3:6]
>>> for i, x in enumerate([x1, x2, x3, x4]):
...     print('x{}'.format(i+1))
...     print(repr(x))
x1
array([[[[0]]],


       [[[1]]],


       [[[2]]]])
x2
array([[[[1]],

        [[2]],

        [[3]]]])
x3
array([[[[2],
         [3],
         [4]]]])
x4
array([[[[3, 4, 5]]]])

>>> # equivalent meshgrid output, note how the first two arguments are reversed and the unpacking
>>> x2, x1, x3, x4 = np.meshgrid(np.arange(1,4), np.arange(3), np.arange(2, 5), np.arange(3, 6), sparse=True)
>>> for i, x in enumerate([x1, x2, x3, x4]):
...     print('x{}'.format(i+1))
...     print(repr(x))
# Identical output so it's omitted here.

Nawet jeśli działają one również dla 1D, istnieją dwie (znacznie bardziej powszechne) funkcje tworzenia siatki 1D:

Oprócz argumentu starti stopobsługuje również stepargument (nawet złożone kroki reprezentujące liczbę kroków):

>>> x1, x2 = np.mgrid[1:10:2, 1:10:4j]
>>> x1  # The dimension with the explicit step width of 2
array([[1., 1., 1., 1.],
       [3., 3., 3., 3.],
       [5., 5., 5., 5.],
       [7., 7., 7., 7.],
       [9., 9., 9., 9.]])
>>> x2  # The dimension with the "number of steps"
array([[ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.]])

Aplikacje

Pytałeś konkretnie o cel, a te siatki są niezwykle przydatne, jeśli potrzebujesz układu współrzędnych.

Na przykład, jeśli masz funkcję NumPy, która oblicza odległość w dwóch wymiarach:

def distance_2d(x_point, y_point, x, y):
    return np.hypot(x-x_point, y-y_point)

I chcesz poznać odległość każdego punktu:

>>> ys, xs = np.ogrid[-5:5, -5:5]
>>> distances = distance_2d(1, 2, xs, ys)  # distance to point (1, 2)
>>> distances
array([[9.21954446, 8.60232527, 8.06225775, 7.61577311, 7.28010989,
        7.07106781, 7.        , 7.07106781, 7.28010989, 7.61577311],
       [8.48528137, 7.81024968, 7.21110255, 6.70820393, 6.32455532,
        6.08276253, 6.        , 6.08276253, 6.32455532, 6.70820393],
       [7.81024968, 7.07106781, 6.40312424, 5.83095189, 5.38516481,
        5.09901951, 5.        , 5.09901951, 5.38516481, 5.83095189],
       [7.21110255, 6.40312424, 5.65685425, 5.        , 4.47213595,
        4.12310563, 4.        , 4.12310563, 4.47213595, 5.        ],
       [6.70820393, 5.83095189, 5.        , 4.24264069, 3.60555128,
        3.16227766, 3.        , 3.16227766, 3.60555128, 4.24264069],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.        , 5.        , 4.        , 3.        , 2.        ,
        1.        , 0.        , 1.        , 2.        , 3.        ],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128]])

Wynik byłby identyczny, gdyby przejść przez gęstą siatkę zamiast otwartej siatki. Nadawanie NumPys umożliwia!

Wizualizujmy wynik:

plt.figure()
plt.title('distance to point (1, 2)')
plt.imshow(distances, origin='lower', interpolation="none")
plt.xticks(np.arange(xs.shape[1]), xs.ravel())  # need to set the ticks manually
plt.yticks(np.arange(ys.shape[0]), ys.ravel())
plt.colorbar()

wprowadź opis zdjęcia tutaj

I to również wtedy, gdy NumPys mgridi ogridstają się bardzo wygodne, ponieważ pozwala łatwo zmienić rozdzielczość twoich siatek:

ys, xs = np.ogrid[-5:5:200j, -5:5:200j]
# otherwise same code as above

wprowadź opis zdjęcia tutaj

Ponieważ jednak imshownie obsługuje xi ydanych wejściowych, należy ręcznie zmieniać tiki. Byłoby naprawdę wygodne, gdyby zaakceptował współrzędne xi y, prawda?

NumPy ułatwia pisanie funkcji, które w naturalny sposób radzą sobie z siatkami. Ponadto istnieje kilka funkcji w NumPy, SciPy, matplotlib, które oczekują przejścia w siatce.

Lubię obrazy, więc zbadajmy matplotlib.pyplot.contour:

ys, xs = np.mgrid[-5:5:200j, -5:5:200j]
density = np.sin(ys)-np.cos(xs)
plt.figure()
plt.contour(xs, ys, density)

wprowadź opis zdjęcia tutaj

Zwróć uwagę, jak współrzędne są już poprawnie ustawione! Nie byłoby tak, gdybyś właśnie zdał density.

Albo dać inny przykład zabawy przy użyciu modeli astropy (tym razem nie obchodzi wiele o współrzędnych, po prostu wykorzystać je do stworzenia jakiegoś siatkę):

from astropy.modeling import models
z = np.zeros((100, 100))
y, x = np.mgrid[0:100, 0:100]
for _ in range(10):
    g2d = models.Gaussian2D(amplitude=100, 
                           x_mean=np.random.randint(0, 100), 
                           y_mean=np.random.randint(0, 100), 
                           x_stddev=3, 
                           y_stddev=3)
    z += g2d(x, y)
    a2d = models.AiryDisk2D(amplitude=70, 
                            x_0=np.random.randint(0, 100), 
                            y_0=np.random.randint(0, 100), 
                            radius=5)
    z += a2d(x, y)

wprowadź opis zdjęcia tutaj

Chociaż jest to tylko „wygląd”, kilka funkcji związanych z modelami funkcjonalnymi i dopasowaniem (na przykład scipy.interpolate.interp2d, scipy.interpolate.griddatanawet pokazuj przykłady użycia np.mgrid) w Scipy itp. Wymaga siatek. Większość z nich działa z otwartymi i gęstymi siatkami, jednak niektóre działają tylko z jedną z nich.

MSeifert
źródło
Chciałbym tylko podziękować za tę niezwykle szczegółową odpowiedź. To poprawiło mój dzień.
Jlanger
Co za piękny sposób na odpowiedź na pytanie ... tak szczegółowy. Dziękuję
Bipin
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- czy nie należy pomnożyć pierwszego zakresu przez 2 km w poziomie i 3 km w pionie przez 2, a drugiego przez 3?
Nixt,
@Nixt Niestety nie jest to takie proste. Być może będę musiał ponownie sprawdzić tę część odpowiedzi. Jest to kompromis między transponowanym wyświetlaniem macierzy a odwróconym indeksowaniem - zwykle oczekuje się, że pierwszy indeks będzie poziomy, a drugi pionowy, ale wówczas ekran zostanie transponowany. Jest to jednak przede wszystkim szczegół, który, miejmy nadzieję, nie unieważnia istoty odpowiedzi, której celem jest zilustrowanie przyczyny powstania siatek. Ale postaram się to poprawić w przyszłości.
MSeifert
36

Załóżmy, że masz funkcję:

def sinus2d(x, y):
    return np.sin(x) + np.sin(y)

i chcesz na przykład zobaczyć, jak to wygląda w zakresie od 0 do 2 * pi. Jak byś to zrobił? Nie np.meshgridjest w:

xx, yy = np.meshgrid(np.linspace(0,2*np.pi,100), np.linspace(0,2*np.pi,100))
z = sinus2d(xx, yy) # Create the image on this grid

i taka fabuła wyglądałaby jak:

import matplotlib.pyplot as plt
plt.imshow(z, origin='lower', interpolation='none')
plt.show()

wprowadź opis zdjęcia tutaj

To np.meshgridtylko wygoda. Zasadniczo to samo można zrobić poprzez:

z2 = sinus2d(np.linspace(0,2*np.pi,100)[:,None], np.linspace(0,2*np.pi,100)[None,:])

ale tam musisz być świadomy swoich wymiarów (załóżmy, że masz więcej niż dwa ...) i właściwego nadawania. np.meshgridrobi to wszystko dla ciebie.

Ponadto meshgrid pozwala usuwać współrzędne wraz z danymi, jeśli na przykład chcesz wykonać interpolację, ale wykluczasz pewne wartości:

condition = z>0.6
z_new = z[condition] # This will make your array 1D

więc jak teraz zrobiłbyś interpolację? Możesz nadać xi ydo funkcji interpolacji scipy.interpolate.interp2dtak, abyś wiedział, które współrzędne zostały usunięte:

x_new = xx[condition]
y_new = yy[condition]

a następnie nadal można interpolować za pomocą „właściwych” współrzędnych (wypróbuj go bez siatki, a będziesz mieć dużo dodatkowego kodu):

from scipy.interpolate import interp2d
interpolated = interp2d(x_new, y_new, z_new)

a oryginalna siatka pozwala ponownie uzyskać interpolację na oryginalnej siatce:

interpolated_grid = interpolated(xx[0], yy[:, 0]).reshape(xx.shape)

To tylko niektóre przykłady, w których użyłem, meshgridmoże być ich znacznie więcej.

MSeifert
źródło
1
Dziękuję za Twoją odpowiedź! Najbardziej mylące moment dla mnie jest zwracane wartości xx, yy. Trudno było zrozumieć, czym one są i dlaczego używamy ich do obliczania funkcji. Wygląda na to, że rozumiem. Chcemy obliczyć jakąś funkcję na podstawie współrzędnych. Możemy napisać coś takiego: for x=1:10: for y=1:10: z[x,y]=sin(x)+sin(y)Zamiast tego obliczamy zw inny sposób z=sin([x,x,...,x]) + sin([y,y,..y]). Popraw mnie, jeśli się mylę!
Alena Kastsiukavets
To nie jest w 100% poprawny pseudo kod, ale mam nadzieję, że
rozumiecie
W rzeczywistości zawsze potrzebujesz podwójnej pętli (pierwszego kodu). Istnieją jednak różne sposoby numpyarchiwizacji za pomocą : siatki lub transmisji. Jeśli nie odrzucisz punktów (patrz ostatnia część mojej odpowiedzi), oba są faktycznie funkcjonalnie równoważne. Nadawanie jest po prostu ukrytą pętlą w wymiarze, który ma być nadawany. Zauważ, że użyłem [:,None]i [None, :]podałem dodatkowe wymiary, aby wynik był poprawnie emitowany. Twój drugi przykład jest bardziej podobny:sin([[y],[y],..[y]])
MSeifert,
Naprawdę miła ilustracja. Dzięki za włożenie tylu wysiłków.
natersoz
interpolated_grid = interpolated(xx, yy)- to mi nie działa, błąd:x and y should both be 1-D arrays
Nixt
4

meshgrid pomaga w tworzeniu prostokątnej siatki z dwóch tablic 1-D wszystkich par punktów z dwóch tablic.

x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 2, 3, 4])

Teraz, jeśli zdefiniowałeś funkcję f (x, y) i chcesz zastosować tę funkcję do wszystkich możliwych kombinacji punktów z tablic „x” i „y”, możesz to zrobić:

f(*np.meshgrid(x, y))

Powiedzmy, że jeśli twoja funkcja tworzy iloczyn dwóch elementów, to w ten sposób można uzyskać produkt kartezjański, skutecznie dla dużych tablic.

Polecony stąd

Narasimhan
źródło
1

Podstawowy pomysł

Biorąc pod uwagę możliwe wartości x xs, (pomyśl o nich jako znaczniki na osi x wykresu) i możliwe wartości y ys, meshgridgeneruje odpowiedni zestaw punktów siatki (x, y) --- analogicznie do set((x, y) for x in xs for y in yx). Na przykład, jeśli xs=[1,2,3]i ys=[4,5,6], otrzymalibyśmy zestaw współrzędnych {(1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (1,6), (2,6), (3,6)}.

Forma wartości zwracanej

Jednak reprezentacja, która meshgridzwraca, różni się od powyższego wyrażenia na dwa sposoby:

Po pierwsze , meshgridokreśla się punkty siatki w 2d tablicy: rzędy odpowiadają różne wartości y, kolumny odpowiadają różne wartości x --- jak w list(list((x, y) for x in xs) for y in ys), co daje następujący układ:

   [[(1,4), (2,4), (3,4)],
    [(1,5), (2,5), (3,5)],
    [(1,6), (2,6), (3,6)]]

Po drugie , meshgridzwraca współrzędne xiy oddzielnie (tj. W dwóch różnych tablicach numpy 2d):

   xcoords, ycoords = (
       array([[1, 2, 3],
              [1, 2, 3],
              [1, 2, 3]]),
       array([[4, 4, 4],
              [5, 5, 5],
              [6, 6, 6]]))
   # same thing using np.meshgrid:
   xcoords, ycoords = np.meshgrid([1,2,3], [4,5,6])
   # same thing without meshgrid:
   xcoords = np.array([xs] * len(ys)
   ycoords = np.array([ys] * len(xs)).T

Uwaga, np.meshgridmożna również generować siatki dla wyższych wymiarów. Biorąc pod uwagę xs, ys i zs, otrzymasz xcoords, ycoords, zcoords jako tablice 3d. meshgridobsługuje także odwrotną kolejność wymiarów, a także rzadkie odwzorowanie wyniku.

Aplikacje

Dlaczego mielibyśmy chcieć tego rodzaju wyników?

Zastosuj funkcję w każdym punkcie siatki: Jedną motywacją jest to, że operatory binarne takie jak (+, -, *, /, **) są przeciążone dla tablic numpy jako operacje elementarne. Oznacza to, że jeśli mam funkcję, def f(x, y): return (x - y) ** 2która działa na dwóch skalarach, mogę również zastosować ją do dwóch tablic numpy, aby uzyskać tablicę wyników elementarnych: np. f(xcoords, ycoords)Lub f(*np.meshgrid(xs, ys))daje następujący przykład w powyższym przykładzie:

array([[ 9,  4,  1],
       [16,  9,  4],
       [25, 16,  9]])

Wyższa wymiarowy produkt zewnętrzna: Nie jestem pewien, jak skuteczne jest to, ale można dostać wysoki-wymiarowy produkty na zewnętrznej w ten sposób: np.prod(np.meshgrid([1,2,3], [1,2], [1,2,3,4]), axis=0).

Wykresy konturowe w matplotlib: Natknąłem się meshgridpodczas badania rysowania wykresów konturowych za pomocą matplotlib w celu wykreślenia granic decyzji . W tym celu generujesz siatkę za pomocą, oceniasz meshgridfunkcję w każdym punkcie siatki (np. Jak pokazano powyżej), a następnie przekazujesz xcoords, ycoords i obliczone wartości F (tj. Zcoords) do funkcji konturu.

użytkownik3780389
źródło