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.
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
.
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')
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')
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".
Dodatkowo, wynik może być teraz przekazywany do funkcji oczekujących danych na siatce prostokątnej (np. contourf
)
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
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()
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.
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:
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")
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")
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()
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
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)
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)
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.
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.
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