Jaki jest cel meshgrid w Pythonie / NumPy?

Może mi ktoś wyjaśnić jaki jest cel meshgrid funkcji w Numpy? Wiem, że tworzy jakąś siatkę współrzędnych do spisku, ale nie widzę bezpośrednich korzyści z tego.

Studiuję "Uczenie maszynowe Pythona" od Sebastiana Raschki, a on 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, wyjście nie ma sensu ja.

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, również Pokaż mi wiele rzeczywistych przykładów.

Author: Suever, 2016-03-15

5 answers

Celem {[5] } jest stworzenie prostokątnej siatki z tablicy wartości X i tablicy wartości Y.

Więc, na przykład, jeśli chcemy stworzyć siatkę, gdzie mamy punkt na każdej wartości całkowitej między 0 i 4 w obu kierunkach x i y. Aby utworzyć siatkę prostokątną, potrzebujemy każdej kombinacji punktów x i y.

To będzie 25 punktów, prawda? Jeśli więc chcemy utworzyć tablicę x i y dla wszystkich tych punktów, możemy wykonać podążam.
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

Wynikałoby to z następujących macierzy x i y, takich że parowanie odpowiedniego elementu w każdej macierzy daje współrzędne x i y 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 je wykreślić, aby sprawdzić, czy są siatką:]}
plt.plot(x,y, marker='.', color='k', linestyle='none')

Tutaj wpisz opis obrazka

Oczywiście, robi się to bardzo uciążliwe, szczególnie dla dużych zakresów x i y. Zamiast tego meshgrid może faktycznie wygenerować to dla nas: wszystko, co musimy określić, to unikalne wartości x i y.

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

Teraz, gdy wywołamy meshgrid, otrzymujemy poprzednie wyjście automatycznie.

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

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

Tutaj wpisz opis obrazka

Tworzenie tych prostokątnych siatek jest przydatne do wielu zadań. W przykładzie, który podałeś w swoim poście, jest to po prostu sposób na próbkowanie funkcji (sin(x**2 + y**2) / (x**2 + y**2)) w zakresie wartości dla x i y.

Ponieważ ta funkcja została pobrana na siatce prostokątnej, funkcja może być teraz wizualizowana jako "obraz".

Tutaj wpisz opis obrazka

Dodatkowo, wynik może być teraz przekazywany do funkcji oczekujących danych na siatce prostokątnej (np. contourf)

 195
Author: Suever,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-29 12:35:37

Dzięki Uprzejmości Microsoft Excelle:

Tutaj wpisz opis obrazka

 106
Author: Hai Phan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 13:27:27

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

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

I chcesz, na przykład, aby zobaczyć, jak to wygląda w zakresie 0 do 2*pi. Jak byś to zrobił? Wchodzi np.meshgrid:

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

A taka fabuła wyglądałaby tak:

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

Tutaj wpisz opis obrazka

Więc np.meshgrid to tylko wygoda. W zasadzie to samo można zrobić przez:

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ściwe nadawanie. np.meshgrid robi to wszystko dla Ciebie.

Również meshgrid pozwala na usunięcie współrzędnych wraz z danymi, jeśli na przykład chcesz wykonać interpolację, ale wykluczyć pewne wartości:

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

Więc jak zrobiłbyś teraz interpolację? Możesz podać x i y do funkcji interpolacyjnej, takiej jak scipy.interpolate.interp2d, więc potrzebujesz sposobu, aby wiedzieć, które współrzędne zostały usunięte:

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

A potem można jeszcze interpolować za pomocą" właściwych " współrzędnych (spróbuj bez meshgrid i będziesz miał dużo dodatkowego kodu):

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

Oryginalna siatka meshgrid pozwala ponownie uzyskać interpolację na oryginalnej siatce:

interpolated_grid = interpolated(xx, yy)

To tylko kilka przykładów, w których użyłem meshgrid Może być o wiele więcej.

 25
Author: MSeifert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 14:50:52

W rzeczywistości cel np.meshgrid jest już wymieniony w dokumentacji:

np.meshgrid

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

Twórz tablice współrzędnych N-D dla wektorowych ocen pól skalarnych / wektorowych n-d nad siatkami N-D, biorąc pod uwagę jednowymiarowe tablice współrzędnych x1, x2,..., xn.

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

Prawdopodobnie właśnie zapytałeś siebie:

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

Powodem, dla którego potrzebujesz macierzy współrzędnych w Pythonie / NumPy, jest to, że nie ma 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 w jakiś sposób przechowywać współrzędne obok swoich danych. Tu wkraczają siatki.

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

1  2  1
2  5  2
1  2  1

Jednak każda wartość reprezentuje obszar szerokości 2 kilometrów w poziomie i 3 kilometry w pionie. Załóżmy, że twoje pochodzenie jest lewym górnym rogu i chcesz tablic, które reprezentują odległość, której możesz użyć:

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

Gdzie h jest:

0  2  4
0  2  4
0  2  4

I h:

0  0  0
3  3  3
6  6  6

Więc jeśli masz dwa indeksy, powiedzmy x i y (dlatego wartość zwracana meshgrid jest zwykle xx lub xs zamiast x w tym przypadku wybrałem h dla poziomo! następnie można uzyskać współrzędną x punktu, współrzędną y punktu i wartość w tym punkcie za pomocą:

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 je przekazać do funkcji, które muszą znać współrzędne.

Nieco dłuższe Wyjaśnienie

Jednak np.meshgrid samo w sobie nie jest często używane bezpośrednio, najczęściej używa się tylko jednego z podobnych obiektów np.mgrid lub np.ogrid. Tutaj np.mgrid reprezentuje sparse=False i np.ogrid przypadek sparse=True (odnoszę się do sparse argumentu np.meshgrid). Należy zauważyć, że istnieje znacząca różnica między np.meshgrid i np.ogrid i np.mgrid: dwie pierwsze zwrócone wartości (jeśli są dwie lub więcej) są odwrócone. Często nie ma to znaczenia, ale należy podać sensowne nazwy zmiennych w zależności od kontekstu. Na przykład w przypadku siatki 2D i matplotlib.pyplot.imshow sensowne jest nazwanie pierwszego zwracanego elementu np.meshgrid x i drugi y gdy jest na odwrót dla np.mgrid i np.ogrid.

np.ogrid i nieliczne 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ż wspomniano wyjście jest odwrócone w porównaniu do np.meshgrid, dlatego rozpakowałem go jako yy, xx zamiast 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, a konkretnie linie x i y dla wykresów 2D.

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

Tutaj wpisz opis obrazka

np.mgrid i gęste / mięsiste 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 ogrid te tablice zawierają wszystkie xx i yy współrzędne w siatce -5

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

Tutaj wpisz opis obrazka

Funkcjonalność

Nie ogranicza się tylko do 2D, funkcje te działają dla dowolnych wymiarów (cóż, istnieje maksymalna liczba argumentów podanych do funkcji w Pythonie i maksymalna liczba wymiary, na które pozwala 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 start i stop wspiera on również argument step (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

Zapytałeś konkretnie o cel i w rzeczywistości te siatki są bardzo 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]])

Wyjście byłoby identyczne, gdyby przejść w gęstej siatce zamiast otwartej siatki. NumPys broadcasting 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()

Tutaj wpisz opis obrazka

I to jest również wtedy, gdy NumPys mgrid i ogrid stają się bardzo wygodne, ponieważ pozwala łatwo zmienić rozdzielczość swoich siatek:

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

Tutaj wpisz opis obrazka

Ponieważ jednak imshow nie obsługuje wejść x i y, należy ręcznie zmieniać kleszcze. Byłoby bardzo wygodnie, gdyby zaakceptował współrzędne x i y, prawda?

Łatwo jest pisać funkcje z NumPy, które zajmują się naturalnie siatkami. Ponadto istnieje kilka funkcji w NumPy, SciPy, MatPlotLib, które oczekują, aby przejść 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)

Tutaj wpisz opis obrazka

Zauważ, że współrzędne są już prawidłowo ustawione! Nie byłoby tak, gdybyś zdała w density.

Albo dać kolejny fajny przykład używając modeli astropii (tym razem nie dbam zbytnio o współrzędne, po prostu używam ich do tworzenia niektórych siatka):

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)

Tutaj wpisz opis obrazka

Chociaż to tylko "dla wyglądu" kilka funkcji związanych z funkcjonalnymi modelami i dopasowaniem (na przykład scipy.interpolate.interp2d, scipy.interpolate.griddata nawet Pokaż przykłady używając np.mgrid) W Scipy, itp. wymagaj siatek. Większość z nich pracuje z otwartymi siatkami i gęste siatki, jednak niektóre działają tylko z jednym z nich.

 15
Author: MSeifert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 22:27:08

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 wytwarza tylko iloczyn dwóch elementów, to tak można osiągnąć iloczyn kartezjański, efektywnie dla dużych tablic.

Tutaj

 0
Author: Narasimhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 10:32:01