Aslında np.meshgrid
dokümantasyonda amaç zaten belirtilmiştir:
np.meshgrid
Koordinat vektörlerinden koordinat matrislerini döndürür.
Tek boyutlu koordinat dizileri x1, x2, ..., xn verilen ND ızgaraları üzerinde ND skaler / vektör alanlarının vektörize değerlendirmeleri için ND koordinat dizileri yapın.
Yani asıl amacı bir koordinat matrisi oluşturmaktır.
Muhtemelen sadece kendinize sordunuz:
Neden koordinat matrisleri oluşturmamız gerekiyor?
Python / NumPy ile koordinat matrislerine ihtiyaç duymanızın nedeni, koordinatlarınızın sıfırla başlaması ve tamamen pozitif tamsayılar dışında, koordinatlardan değerlere doğrudan bir ilişkisinin olmamasıdır. Daha sonra bir dizinin dizinlerini dizin olarak kullanabilirsiniz. Ancak durum böyle olmadığında, verilerinizin yanında koordinatları bir şekilde depolamanız gerekir. Izgaralar burada devreye giriyor.
Verilerinizin:
1 2 1
2 5 2
1 2 1
Ancak, her bir değer yatay olarak 2 kilometre genişliğinde ve dikey olarak 3 kilometre genişliğindedir. Kökeninizin sol üst köşede olduğunu ve kullanabileceğiniz mesafeyi temsil eden diziler istediğinizi varsayalım:
import numpy as np
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)
burada v:
array([[0, 0, 0],
[2, 2, 2],
[4, 4, 4]])
ve h:
array([[0, 3, 6],
[0, 3, 6],
[0, 3, 6]])
İki endeks var ise, diyelim ki x
ve y
(dönüş değeri neden en yani meshgrid
genellikle xx
ya xs
yerine x
ben seçtim bu durumda h
o zaman x noktasının koordinatı alabilirsiniz yatay için!), Y noktası ve koordinatı bu noktadaki değeri kullanarak:
h[x, y] # horizontal coordinate
v[x, y] # vertical coordinate
data[x, y] # value
Bu, koordinatları takip etmeyi çok daha kolay hale getirir ve (daha da önemlisi) onları koordinatları bilmesi gereken işlevlere geçirebilirsiniz.
Biraz daha uzun bir açıklama
Ancak, np.meshgrid
kendisi genellikle doğrudan kullanılmaz, çoğunlukla biri sadece benzer nesnelerden birini kullanır np.mgrid
veya np.ogrid
. Burada np.mgrid
temsil sparse=False
ve dava (I atıfta argümanı ). Ve ile arasında önemli bir fark olduğunu unutmayın
: Döndürülen ilk iki değer (iki veya daha fazla varsa) tersine çevrilir. Genellikle bu önemli değildir, ancak bağlama bağlı olarak anlamlı değişken adları vermelisiniz.np.ogrid
sparse=True
sparse
np.meshgrid
np.meshgrid
np.ogrid
np.mgrid
Örneğin, bir 2B ızgara durumunda ve matplotlib.pyplot.imshow
bunun ilk iade öğeyi isim mantıklı np.meshgrid
x
ve ikincisini y
ne için tersi ise np.mgrid
ve np.ogrid
.
np.ogrid
ve seyrek ızgaralar
>>> 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]])
Daha önce de belirtildiği gibi, çıktı ile karşılaştırıldığında tersine çevrildi np.meshgrid
, bu yüzden yy, xx
bunun yerine paketini açtım 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]])
Bu zaten koordinatlara benziyor, özellikle 2B grafikler için x ve y çizgileri.
görsel:
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
ve yoğun / etli ızgaralar
>>> 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]])
Aynısı burada da geçerlidir: Çıktı aşağıdakilerle karşılaştırıldığında tersine çevrilir 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]])
ogrid
Bu dizilerin aksine -5 <= xx <= 5 içindeki tüm xx
ve yy
koordinatları içerir ; -5 <= yy <= 5 ızgara.
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")
İşlevsellik
Sadece 2B ile sınırlı değildir, bu işlevler keyfi boyutlar için çalışır (Python'da işlev için maksimum sayıda argüman ve NumPy'nin izin verdiği maksimum boyut sayısı vardır):
>>> 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.
Bunlar 1D için de çalışsa bile iki (çok daha yaygın) 1D ızgara oluşturma işlevi vardır:
start
Ve stop
argümanının yanı sıra argümanı da destekler step
(adım sayısını temsil eden karmaşık adımlar bile):
>>> 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.]])
Uygulamalar
Özellikle amacı sordunuz ve aslında bir koordinat sistemine ihtiyacınız varsa bu ızgaralar son derece kullanışlıdır.
Örneğin, mesafeyi iki boyutta hesaplayan bir NumPy işleviniz varsa:
def distance_2d(x_point, y_point, x, y):
return np.hypot(x-x_point, y-y_point)
Ve her noktanın mesafesini bilmek istersiniz:
>>> 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]])
Biri açık bir ızgara yerine yoğun bir ızgaradan geçtiğinde çıktı aynı olacaktır. NumPys yayını mümkün kılar!
Sonucu görselleştirelim:
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()
Ve bu da NumPys olduğunda mgrid
ve ogrid
çok uygun hale geldiğinde, çünkü ızgaralarınızın çözünürlüğünü kolayca değiştirmenize izin verir:
ys, xs = np.ogrid[-5:5:200j, -5:5:200j]
# otherwise same code as above
Ancak, imshow
desteklemediğinden x
ve y
girdiler desteklenmediğinden , kenelerin elle değiştirilmesi gerekir. x
Ve y
koordinatlarını kabul etmesi gerçekten uygun olurdu , değil mi?
Izgaralarla doğal olarak ilgilenen NumPy ile fonksiyon yazmak kolaydır. Ayrıca, NumPy, SciPy, matplotlib'de ızgaraya geçmenizi bekleyen çeşitli işlevler vardır.
Görüntüleri seviyorum, bu yüzden keşfedelim 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)
Koordinatların nasıl doğru ayarlandığına dikkat edin! Eğer daha yeni geçmiş olsaydın durum böyle olmazdı density
.
Veya astropi modelleri kullanarak başka bir eğlenceli örnek vermek için (bu sefer koordinatlar hakkında pek umurumda değil, sadece bazı ızgaralar oluşturmak için kullanıyorum ):
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)
Bu sadece "görünümler için" olmasına rağmen, Scipy, vs.'deki fonksiyonel modeller ve fitting ile ilgili çeşitli işlevler (örneğin scipy.interpolate.interp2d
,
scipy.interpolate.griddata
örnekleri kullanarak bile göster np.mgrid
) ızgaralar gerektirir. Bunların çoğu açık ızgaralar ve yoğun ızgaralarla çalışır, ancak bazıları sadece bunlardan biriyle çalışır.
xx
veyy
. Benim için gizemli kısım, neden bu sonuç çiftini ve neye benzediklerini geri döndürmesiydi. Hai Phan'ın cevabı bunun için kullanışlıdır. Sanırım kolaylık sağlamak için bunu yapıyor, çünkü arsa böyle iki parametre istiyor.