จุดประสงค์ของ meshgrid ใน Python / NumPy คืออะไร?


302

บางคนสามารถอธิบายให้ฉันฟังได้ว่าอะไรคือจุดประสงค์ของmeshgridฟังก์ชั่นใน Numpy? ฉันรู้ว่ามันสร้างกริดพิกัดบางอย่างสำหรับการวางแผน แต่ฉันไม่เห็นประโยชน์โดยตรงของมัน

ฉันกำลังศึกษา "Python Machine Learning" จาก Sebastian Raschka และเขาใช้เพื่อวางแผนขอบเขตการตัดสินใจ เห็นอินพุต 11 ที่นี่

ฉันได้ลองใช้รหัสนี้จากเอกสารอย่างเป็นทางการแล้ว แต่ผลลัพธ์ก็ไม่สมเหตุสมผลสำหรับฉัน

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)

กรุณาถ้าเป็นไปได้แสดงตัวอย่างจริงมากมายให้ฉันด้วย

คำตอบ:


388

วัตถุประสงค์ของmeshgridการสร้างตารางสี่เหลี่ยมออกจากอาร์เรย์ของค่า x และอาร์เรย์ของค่า y

ตัวอย่างเช่นถ้าเราต้องการสร้างกริดที่เรามีจุดที่ค่าจำนวนเต็มแต่ละค่าระหว่าง 0 ถึง 4 ทั้งในทิศทาง x และ y ในการสร้างกริดสี่เหลี่ยมเราต้องรวมกันของxและyจุด

นี่จะเป็น 25 คะแนนจริงไหม? ดังนั้นหากเราต้องการสร้างอาร์เรย์ x และ 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

สิ่งนี้จะส่งผลต่อไปนี้xและyเมทริกซ์เช่นการจับคู่ขององค์ประกอบที่สอดคล้องกันในแต่ละเมทริกซ์ให้พิกัด x และ y ของจุดในกริด

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

จากนั้นเราสามารถพล็อตสิ่งเหล่านี้เพื่อตรวจสอบว่าเป็นกริด:

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

ป้อนคำอธิบายรูปภาพที่นี่

เห็นได้ชัดว่านี้ได้รับน่าเบื่อมากโดยเฉพาะอย่างยิ่งสำหรับช่วงขนาดใหญ่และx yแต่meshgridสามารถสร้างสิ่งนี้ให้กับเราได้จริง: ทั้งหมดที่เราต้องระบุมีค่าxและyค่าเฉพาะ

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

ตอนนี้เมื่อเราเรียกmeshgridเราได้รับผลลัพธ์ก่อนหน้าโดยอัตโนมัติ

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

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

ป้อนคำอธิบายรูปภาพที่นี่

การสร้างกริดสี่เหลี่ยมเหล่านี้มีประโยชน์สำหรับงานหลายอย่าง ในตัวอย่างที่คุณได้ให้ไว้ในการโพสต์ของคุณก็เป็นเพียงวิธีการที่จะลิ้มลองฟังก์ชั่น (กsin(x**2 + y**2) / (x**2 + y**2)) ในช่วงของค่าสำหรับและxy

เนื่องจากฟังก์ชั่นนี้ได้รับการสุ่มตัวอย่างในตารางสี่เหลี่ยมตอนนี้ฟังก์ชั่นจึงสามารถมองเห็นเป็น "ภาพ"

ป้อนคำอธิบายรูปภาพที่นี่

นอกจากนี้ผลลัพธ์ยังสามารถส่งผ่านไปยังฟังก์ชันที่คาดว่าข้อมูลในตารางสี่เหลี่ยม (เช่นcontourf)


10
คุณยังไม่ได้อธิบายค่าผลตอบแทนและxx yyส่วนที่ลึกลับสำหรับฉันคือเหตุผลที่ส่งคืนผลลัพธ์คู่นั้นและสิ่งที่พวกเขาดูเหมือน คำตอบของ Hai Phan นั้นมีประโยชน์สำหรับเรื่องนั้น ฉันเดาว่าทำเพื่อความสะดวกเนื่องจากพล็อตต้องการพารามิเตอร์สองตัวเช่นนั้น
nealmcb

2
ฉันไม่รู้ - นั่นคือเหตุผลที่ฉันกำลังหาข้อมูลนี้;) ดังนั้นฉันไม่ได้บอกว่ามันควรจะคืนสิ่งที่แตกต่าง ฉันแค่ให้การคาดเดาที่ดีที่สุดกับข้อมูลที่ขาดหายไปสำหรับผู้ที่เพิ่งอ่านคำตอบที่ได้รับการยอมรับ และถ้าคุณชอบฉันขอแนะนำว่าคำตอบของคุณ (ซึ่งดีมากแล้ว - ขอบคุณ!) จะสมบูรณ์กว่านี้เล็กน้อยถ้าคุณอธิบายค่าตอบแทน (เช่นเดียวกับไห่) สำหรับพวกเราที่ยังงงอยู่
nealmcb

1
เพื่อให้เข้าใจค่าของ xx และ yy ได้ดียิ่งขึ้นให้พิจารณาการอ้างสิทธิ์ว่าโค้ดต่อไปนี้ทำให้คุณได้ผลลัพธ์เช่นเดียวกับ np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Matt Kleinsmith

1
คำตอบนี้ทำให้เกิดความสับสน - ภาพประกอบแรกxและyหลังของคุณไม่ใช่หรือ? เมื่อคุณทำxx, yy = np.meshgrid(np.arange(4), np.arange(4))มันเป็นสิ่งที่ตรงกันข้ามของสิ่งที่คุณมีxและyในส่วนแรกของคำตอบ มันตรงกับคำสั่งของเอาท์พุทmgridแต่ไม่ใช่ meshgrid xxควรจะเพิ่มขึ้นในทิศทาง -x แต่คุณเพิ่มขึ้นในทิศทาง Y
Scott Staniewicz

1
@ScottStaniewicz ขอบคุณที่ชี้ให้เราเห็นว่าฉันทำสิ่งนั้นผิดพลาด ... อัปเดต!
Suever

249

มารยาทของ Microsoft Excel: 

ป้อนคำอธิบายรูปภาพที่นี่


6
ดี FWIW ถ้าคุณต้องการ 2 x 12 อาร์เรย์ของคู่ที่อยู่ตรงกลาง:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
เดนิส

5
และถ้าคุณต้องการ 12 x 2 อาร์เรย์ของคู่ที่อยู่ตรงกลาง:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn

2
คำตอบที่ดี วัตถุประสงค์ของ meshgrid คือการสร้างกริดโดยใช้พิกัดของแต่ละสลัว
เด็กดี

1
สิ่งที่ฉันคิดว่าแปลกเล็กน้อยคือค่า x และ y จะถูกส่งกลับแยกกันแทนที่จะรวมกันเป็นหนึ่งอาร์เรย์ ถ้าฉันต้องการมันในหนึ่งอาเรย์ฉันต้องทำ:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892

64

จริงๆแล้ววัตถุประสงค์ของการnp.meshgridพูดถึงในเอกสาร:

np.meshgrid

ส่งคืนเมทริกซ์พิกัดจากเวกเตอร์พิกัด

จัดทำอาร์เรย์พิกัด ND สำหรับการประเมินเวกเตอร์ของสนาม ND scalar / vector บน ND กริดซึ่งกำหนดอาร์เรย์อาร์เรย์หนึ่งมิติ x1, x2, ... , xn

ดังนั้นวัตถุประสงค์หลักคือการสร้างเมทริกซ์พิกัด

คุณอาจถามตัวเองว่า:

ทำไมเราต้องสร้างเมทริกซ์พิกัด?

เหตุผลที่คุณต้องการเมทริกซ์ประสานงานกับ Python / NumPy คือไม่มีความสัมพันธ์โดยตรงจากพิกัดกับค่ายกเว้นเมื่อพิกัดของคุณเริ่มต้นด้วยศูนย์และเป็นจำนวนเต็มบวกล้วนๆ จากนั้นคุณสามารถใช้ดัชนีของอาร์เรย์เป็นดัชนีได้ อย่างไรก็ตามในกรณีที่คุณไม่จำเป็นต้องจัดเก็บพิกัดข้างข้อมูลของคุณ นั่นคือที่มาของกริด

สมมติว่าข้อมูลของคุณคือ:

1  2  1
2  5  2
1  2  1

อย่างไรก็ตามแต่ละค่าแสดงพื้นที่กว้าง 2 กิโลเมตรในแนวนอนและ 3 กิโลเมตรในแนวตั้ง สมมติว่าต้นกำเนิดของคุณอยู่ที่มุมซ้ายบนและคุณต้องการอาร์เรย์ที่แสดงระยะทางที่คุณสามารถใช้:

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

โดยที่ v คือ:

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

และ h:

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

ดังนั้นถ้าคุณมีสองดัชนี, สมมุติว่าxและy(นั่นคือสาเหตุที่ค่าส่งคืนของmeshgridคือปกติxxหรือxsแทนxในกรณีนี้ฉันเลือกhสำหรับแนวนอน!) จากนั้นคุณจะได้พิกัด x ของจุด, พิกัด y ของจุดและ ค่า ณ จุดนั้นโดยใช้:

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

ทำให้ง่ายต่อการติดตามพิกัดและ (สำคัญยิ่งกว่า) คุณสามารถส่งผ่านไปยังฟังก์ชันที่ต้องรู้พิกัด

คำอธิบายที่ยาวขึ้นเล็กน้อย

แต่np.meshgridตัวเองไม่ได้มักจะมาใช้โดยตรงส่วนใหญ่เพียงแค่ใช้อย่างใดอย่างหนึ่งคล้ายวัตถุหรือnp.mgrid np.ogridนี่np.mgridหมายถึงsparse=Falseและกรณี (ผมหมายถึงข้อโต้แย้งของ) โปรดทราบว่ามีความแตกต่างอย่างมีนัยสำคัญระหว่าง และกับ: ค่าที่ส่งคืนสองค่าแรก (หากมีสองค่าขึ้นไป) จะถูกกลับรายการ บ่อยครั้งที่สิ่งนี้ไม่สำคัญ แต่คุณควรให้ชื่อตัวแปรที่มีความหมายขึ้นอยู่กับบริบทnp.ogridsparse=Truesparsenp.meshgridnp.meshgridnp.ogridnp.mgrid

ยกตัวอย่างเช่นในกรณีของตาราง 2D และmatplotlib.pyplot.imshowมันทำให้รู้สึกถึงชื่อรายการแรกของกลับnp.meshgrid xและเป็นคนที่สองyในขณะที่มันเป็นวิธีอื่น ๆ รอบและnp.mgridnp.ogrid

np.ogrid และกระจัดกระจายกริด

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

อย่างที่บอกไปแล้วว่าเอาท์พุทกลับด้านเมื่อเทียบกับnp.meshgridนั่นคือเหตุผลที่ฉันเอามันออกมาyy, xxแทน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]])

นี่ดูเหมือนพิกัดแล้วโดยเฉพาะเส้น x และ y สำหรับแปลง 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 และกริดหนาแน่น / เนื้อออก

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

เช่นเดียวกับที่นี่: ผลลัพธ์จะถูกย้อนกลับเมื่อเทียบกับ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อาร์เรย์เหล่านี้มีทั้งหมด xxและyyพิกัดใน -5 <= xx <= 5; -5 <= yy <= 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")

ป้อนคำอธิบายรูปภาพที่นี่

ฟังก์ชั่น

มันไม่ได้ จำกัด อยู่เพียงแค่ 2D เท่านั้นฟังก์ชันเหล่านี้ทำงานสำหรับมิติข้อมูลโดยพลการ

>>> 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.

แม้ว่าสิ่งเหล่านี้ยังสามารถใช้งานได้กับ 1D แต่ก็มีฟังก์ชั่นการสร้างกริด 1D ที่สอง (มากกว่าปกติ):

นอกจากนี้startและstopยังสนับสนุนstepอาร์กิวเมนต์ (ขั้นตอนที่ซับซ้อนที่แสดงถึงจำนวนของขั้นตอน):

>>> 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.]])

การประยุกต์ใช้งาน

คุณถามเกี่ยวกับวัตถุประสงค์และในความเป็นจริงแล้วกริดเหล่านี้มีประโยชน์อย่างยิ่งหากคุณต้องการระบบพิกัด

ตัวอย่างเช่นหากคุณมีฟังก์ชัน NumPy ที่คำนวณระยะทางในสองมิติ:

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

และคุณต้องการทราบระยะทางของแต่ละจุด:

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

เอาต์พุตจะเหมือนกันหากมีการส่งผ่านในกริดหนาแน่นแทนที่จะเป็นกริดเปิด การถ่ายทอด NumPys ทำให้เป็นไปได้!

ลองนึกภาพผลลัพธ์:

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

ป้อนคำอธิบายรูปภาพที่นี่

และนี่ก็เป็นเมื่อ NumPys mgridและogridสะดวกมากเพราะช่วยให้คุณเปลี่ยนความละเอียดของเส้นกริดของคุณได้อย่างง่ายดาย:

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

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามเนื่องจากimshowไม่รองรับxและyอินพุตหนึ่งจึงต้องเปลี่ยนเห็บด้วยมือ มันจะสะดวกจริงๆถ้าจะยอมรับxและyพิกัดใช่มั้ย

มันง่ายที่จะเขียนฟังก์ชั่นด้วย NumPy ซึ่งจัดการกับกริดอย่างเป็นธรรมชาติ นอกจากนี้ยังมีฟังก์ชั่นหลายอย่างใน NumPy, SciPy, matplotlib ที่คาดว่าคุณจะผ่านในกริด

ฉันชอบรูปภาพลองมาสำรวจ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)

ป้อนคำอธิบายรูปภาพที่นี่

สังเกตวิธีการตั้งค่าพิกัดอย่างถูกต้องแล้ว! densityไม่ว่าจะเป็นกรณีที่ถ้าคุณเพิ่งผ่านใน

หรือเพื่อให้ตัวอย่างสนุกอื่นโดยใช้แบบจำลอง astropy (คราวนี้ผมไม่สนใจมากเกี่ยวกับพิกัดฉันเพียงแค่ใช้ในการสร้างบางตาราง):

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)

ป้อนคำอธิบายรูปภาพที่นี่

ถึงแม้ว่ามันจะเป็นเพียงแค่ "สำหรับรูปลักษณ์" ฟังก์ชั่นต่างๆที่เกี่ยวข้องกับรูปแบบการทำงานและเหมาะสม (เช่นscipy.interpolate.interp2d, scipy.interpolate.griddataได้แสดงตัวอย่างการใช้np.mgrid) ใน SciPy ฯลฯ ต้องกริด งานเหล่านี้ส่วนใหญ่มีกริดแบบเปิดและกริดแบบหนาแน่น แต่บางงานจะทำงานร่วมกับหนึ่งในนั้นเท่านั้น


ฉันแค่อยากจะบอกว่าขอบคุณมากสำหรับคำตอบที่ละเอียดมากนี้ นี่ทำให้วันของฉัน
Jlanger

ช่างเป็นวิธีที่สวยงามในการตอบคำถาม .... มีรายละเอียดมาก ขอบคุณ
Bipin

h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- ตั้งแต่แนวนอน 2 กม. และแนวตั้ง 3 กม. ช่วงแรกไม่ควรคูณด้วย 2 และสองคูณ 3?
Nixt

@ ไม่น่าเสียดาย แต่มันไม่ง่ายอย่างนั้น ฉันอาจต้องตรวจสอบคำตอบส่วนนั้นอีกครั้ง เป็นการแลกเปลี่ยนระหว่างการแสดงเมทริกซ์ที่ถูกย้ายและการสลับดัชนี - โดยปกติคุณคาดหวังว่าดัชนีแรกจะเป็นแนวนอนและแนวตั้งที่สอง แต่จากนั้นจอแสดงผลจะถูกย้าย อย่างไรก็ตามนี่เป็นรายละเอียดส่วนใหญ่ซึ่งหวังว่าจะไม่ทำให้ข้อมูลสำคัญของคำตอบไม่ถูกต้องซึ่งมีวัตถุประสงค์เพื่อแสดงเหตุผลของกริด แต่ฉันจะพยายามแก้ไขในวันที่ในอนาคต
MSeifert

36

สมมติว่าคุณมีฟังก์ชั่น:

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

ตัวอย่างเช่นคุณต้องการดูว่ามีลักษณะอย่างไรในช่วง 0 ถึง 2 * pi คุณจะทำอย่างไร มี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

และพล็อตดังกล่าวจะมีลักษณะ:

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

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นจึงnp.meshgridเป็นเพียงความสะดวกสบาย ในหลักการเดียวกันสามารถทำได้โดย:

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

แต่ที่นั่นคุณต้องระวังมิติของคุณ (สมมติว่าคุณมีมากกว่าสอง ... ) และการออกอากาศที่ถูกต้อง np.meshgridทำทั้งหมดนี้ให้คุณ

meshgrid ยังอนุญาตให้คุณลบพิกัดพร้อมกับข้อมูลถ้าคุณต้องการทำการแก้ไข แต่ไม่รวมค่าบางอย่าง:

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

ดังนั้นคุณจะทำการแก้ไขได้อย่างไร คุณสามารถมอบxและyให้ฟังก์ชันการประมาณค่าเช่นscipy.interpolate.interp2dนั้นดังนั้นคุณต้องการวิธีที่จะทราบว่าพิกัดใดที่ถูกลบ:

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

แล้วคุณยังสามารถแก้ไขด้วยพิกัด "ขวา" (ลองโดยไม่ต้อง meshgrid และคุณจะมีรหัสพิเศษมากมาย):

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

และ meshgrid ดั้งเดิมช่วยให้คุณได้รับการแก้ไขในตารางเดิมอีกครั้ง:

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

นี่เป็นเพียงตัวอย่างที่ฉันใช้meshgridอาจจะมีมากขึ้น


1
ขอบคุณสำหรับคำตอบ! ช่วงเวลาที่สับสนที่สุดสำหรับฉันคือการคืนค่าxx, yy. มันยากที่จะเข้าใจว่ามันคืออะไรและทำไมเราใช้มันเพื่อคำนวณฟังก์ชัน ดูเหมือนว่าฉันเข้าใจแล้ว เราต้องการคำนวณฟังก์ชั่นบางอย่างตามพิกัด เราสามารถเขียนสิ่งนี้: for x=1:10: for y=1:10: z[x,y]=sin(x)+sin(y)แทนที่จะคำนวณzในวิธีที่ต่างออกz=sin([x,x,...,x]) + sin([y,y,..y])ไป ถูกต้องฉันถ้าฉันผิด!
Alena Kastsiukavets

มันไม่ได้ 100% รหัสเทียมที่ถูกต้อง แต่ฉันหวังว่าคุณจะเห็นจุดของฉัน)
Alena Kastsiukavets

จริงๆแล้วคุณต้องมีการวนซ้ำสองครั้ง (รหัสแรกของคุณ) แต่มีวิธีการที่แตกต่างกันในการจัดเก็บด้วยnumpy: ตาข่ายหรือการออกอากาศ หากคุณไม่ละทิ้งประเด็น (ดูส่วนสุดท้ายของคำตอบของฉัน) ทั้งสองแบบนั้นใช้งานได้จริง การแพร่ภาพเป็นเพียงการวนซ้ำโดยปริยายในมิติที่ต้องการออกอากาศ โปรดทราบว่าฉันใช้[:,None]และ[None, :]รวมส่วนข้อมูลเพิ่มเติมเพื่อให้ผลลัพธ์ออกอากาศอย่างถูกต้อง ตัวอย่างที่สองของคุณเป็นเหมือน:sin([[y],[y],..[y]])
MSeifert

ภาพประกอบที่ดีจริงๆ ขอบคุณสำหรับความพยายามอย่างมาก
natersoz

interpolated_grid = interpolated(xx, yy)- สิ่งนี้ใช้ไม่ได้สำหรับฉันข้อผิดพลาด:x and y should both be 1-D arrays
Nixt

4

meshgrid ช่วยในการสร้างตารางสี่เหลี่ยมจาก 1-D สองอาร์เรย์ของคะแนนทั้งหมดจากสองอาร์เรย์

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

ทีนี้ถ้าคุณกำหนดฟังก์ชัน f (x, y) และคุณต้องการใช้ฟังก์ชันนี้กับการรวมกันของคะแนนจากอาร์เรย์ 'x' และ 'y' ทั้งหมดคุณสามารถทำสิ่งนี้ได้:

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

สมมติว่าหากฟังก์ชันของคุณเพียงแค่สร้างผลิตภัณฑ์ที่มีสององค์ประกอบนี่ก็เป็นวิธีที่จะทำให้ผลิตภัณฑ์คาร์ทีเซียนสามารถทำได้อย่างมีประสิทธิภาพสำหรับอาร์เรย์ขนาดใหญ่

อ้างอิงจากที่นี่


1

ความคิดพื้นฐาน

ได้รับค่า x เป็นไปได้xs(คิดว่าพวกเขาเป็นเห็บเครื่องหมายบนแกน x ของพล็อต) และค่า y ที่เป็นไปได้ys, meshgridสร้างชุดที่สอดคล้องกันของ (x, y) จุดกริด --- set((x, y) for x in xs for y in yx)คล้ายคลึงกับ ตัวอย่างเช่นถ้าxs=[1,2,3]และเราจะได้รับชุดของพิกัดys=[4,5,6]{(1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (1,6), (2,6), (3,6)}

รูปแบบของมูลค่าส่งคืน

อย่างไรก็ตามการแสดงที่meshgridส่งคืนนั้นแตกต่างจากนิพจน์ด้านบนในสองวิธี:

ก่อนอื่นให้meshgridวางจุดกริดในอาร์เรย์ 2d: แถวสอดคล้องกับค่า y ที่แตกต่างกันคอลัมน์สอดคล้องกับค่า x ที่แตกต่างกัน --- list(list((x, y) for x in xs) for y in ys)ซึ่งจะให้อาร์เรย์ต่อไปนี้:

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

ประการที่สอง , meshgridผลตอบแทนที่ x และ y พิกัดแยกต่างหาก (เช่นในสองอาร์เรย์ 2 มิติที่แตกต่างกัน numpy):

   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

หมายเหตุnp.meshgridยังสามารถสร้างกริดสำหรับขนาดที่สูงขึ้นได้ ให้ xs, ys และ zs, คุณจะได้ xcoords กลับมา, ycoords, zcoords เป็นอาร์เรย์ 3 มิติ meshgridยังรองรับการเรียงลำดับแบบย้อนกลับของมิติรวมถึงการแสดงผลลัพธ์แบบเบาบาง

การประยุกต์ใช้งาน

ทำไมเราถึงต้องการรูปแบบผลลัพธ์นี้

ใช้ฟังก์ชั่นที่จุดทุกจุดบนกริด: หนึ่งแรงจูงใจคือตัวดำเนินการแบบไบนารีเช่น (+, -, *, /, **) มีการโอเวอร์โหลดสำหรับอาร์เรย์ที่มีจำนวนมากซึ่งเป็นการดำเนินการตามองค์ประกอบ ซึ่งหมายความว่าหากฉันมีฟังก์ชั่นdef f(x, y): return (x - y) ** 2ที่ใช้งานได้กับสองสเกลาร์ฉันสามารถนำไปใช้กับอาร์เรย์ numpy สองชุดเพื่อรับผลลัพธ์ขององค์ประกอบตามลำดับ: ตัวอย่างf(xcoords, ycoords)หรือf(*np.meshgrid(xs, ys))ให้ตัวอย่างต่อไปนี้:

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

อุดมศึกษามิติสินค้านอก:ผมไม่แน่ใจว่าวิธีการที่มีประสิทธิภาพนี้ np.prod(np.meshgrid([1,2,3], [1,2], [1,2,3,4]), axis=0)แต่คุณสามารถได้รับสูงมิติผลิตภัณฑ์ด้านนอกด้วยวิธีนี้:

แปลงรูปโฉมใน matplotlib:ฉันมาข้ามmeshgridเมื่อตรวจสอบการวาดภาพแปลงรูปร่างกับ matplotlibสำหรับพล็อตขอบเขตการตัดสินใจ สำหรับสิ่งนี้คุณสร้างกริดด้วยmeshgridประเมินฟังก์ชันที่แต่ละจุดกริด (เช่นดังที่แสดงด้านบน) จากนั้นผ่าน xcoords, ycoords และคำนวณค่า f (เช่น zcoords) ลงในฟังก์ชัน contourf

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.