Mục đích của lướigrid trong Python / NumPy là gì?


302

Ai đó có thể giải thích cho tôi mục đích của meshgridchức năng trong Numpy là gì không? Tôi biết nó tạo ra một số loại lưới tọa độ cho âm mưu, nhưng tôi thực sự không thể thấy lợi ích trực tiếp của nó.

Tôi đang nghiên cứu "Python Machine Learning" từ Sebastian Raschka, và anh ta đang sử dụng nó để vạch ra các biên giới quyết định. Xem đầu vào 11 tại đây .

Tôi cũng đã thử mã này từ tài liệu chính thức, nhưng, một lần nữa, đầu ra không thực sự có ý nghĩa với tôi.

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)

Xin vui lòng, nếu có thể, cũng cho tôi thấy rất nhiều ví dụ thực tế.

Câu trả lời:


389

Mục đích của meshgridviệc tạo ra một lưới hình chữ nhật từ một mảng các giá trị x và một mảng các giá trị y.

Vì vậy, ví dụ, nếu chúng ta muốn tạo một lưới trong đó chúng ta có một điểm tại mỗi giá trị số nguyên từ 0 đến 4 theo cả hai hướng x và y. Để tạo một lưới hình chữ nhật, chúng ta cần mọi sự kết hợp của các điểm xy.

Đây sẽ là 25 điểm, phải không? Vì vậy, nếu chúng ta muốn tạo một mảng x và y cho tất cả các điểm này, chúng ta có thể làm như sau.

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

Điều này sẽ dẫn đến các ma trận sau xyma trận, sao cho việc ghép các phần tử tương ứng trong mỗi ma trận sẽ cho tọa độ x và y của một điểm trong lưới.

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

Sau đó chúng ta có thể vẽ những thứ này để xác minh rằng chúng là một lưới:

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

nhập mô tả hình ảnh ở đây

Rõ ràng, điều này trở nên rất tẻ nhạt, đặc biệt là đối với phạm vi lớn xy. Thay vào đó, meshgridthực sự có thể tạo ra điều này cho chúng ta: tất cả những gì chúng ta phải chỉ định là duy nhất xycác giá trị.

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

Bây giờ, khi chúng tôi gọi meshgrid, chúng tôi nhận được đầu ra trước đó tự động.

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

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

nhập mô tả hình ảnh ở đây

Tạo các lưới hình chữ nhật này rất hữu ích cho một số nhiệm vụ. Trong ví dụ mà bạn đã cung cấp trong bài đăng của mình, nó chỉ đơn giản là một cách để lấy mẫu một hàm ( sin(x**2 + y**2) / (x**2 + y**2)) qua một phạm vi các giá trị cho xy.

Vì chức năng này đã được lấy mẫu trên lưới hình chữ nhật, giờ đây chức năng có thể được hiển thị dưới dạng "hình ảnh".

nhập mô tả hình ảnh ở đây

Ngoài ra, kết quả hiện có thể được chuyển đến các hàm mong đợi dữ liệu trên lưới hình chữ nhật (nghĩa là contourf)


10
Bạn đã không giải thích các giá trị trả về xxyy. Phần bí ẩn đối với tôi là tại sao nó trả về cặp kết quả đó, và chúng trông như thế nào. Câu trả lời của Hải Phan rất hữu ích cho việc đó. Tôi đoán nó làm điều đó cho thuận tiện, vì cốt truyện muốn hai tham số như thế.
nealmcb

2
Tôi không biết - đó là lý do tại sao tôi tìm kiếm thông tin này;) Vì vậy, tôi không nói rằng nó sẽ trả lại một cái gì đó khác biệt. Tôi chỉ cung cấp dự đoán tốt nhất của tôi về một thông tin còn thiếu cho những người chỉ đọc câu trả lời được chấp nhận. Và nếu bạn thích, tôi đề nghị rằng câu trả lời của bạn (đã rất hay - cảm ơn bạn!) Sẽ đầy đủ hơn một chút nếu bạn giải thích các giá trị trả về (như Hải đã làm), đối với những người trong chúng ta vẫn còn bối rối.
nealmcb

1
Để hiểu rõ hơn về các giá trị của xx và yy, hãy xem xét khiếu nại rằng đoạn mã sau mang lại cho bạn kết quả tương tự như np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Matt Kleinsmith

1
Câu trả lời này khó hiểu - Không phải là minh họa đầu tiên của bạn về xyngược? Khi bạn làm xx, yy = np.meshgrid(np.arange(4), np.arange(4)), nó là đảo ngược của những gì bạn có xytrong phần đầu tiên của câu trả lời. Nó phù hợp với thứ tự của các đầu ra cho mgrid, nhưng không phải là lưới. Các xxNên tăng trong x-hướng, nhưng bạn tăng theo phương y.
Scott Staniewicz

1
@ScottStaniewicz Cảm ơn bạn đã chỉ ra rằng, bây giờ chắc chắn làm thế nào tôi đã gửi nó lên ... Đã cập nhật!
Suever

249

Lịch sự của Microsoft Excel: 

nhập mô tả hình ảnh ở đây


6
Đẹp. Fwiw, nếu bạn muốn một mảng 2 x 12 của các cặp ở giữa:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
denis

5
và nếu bạn muốn một mảng 12 x 2 của các cặp ở giữa:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn

2
Câu trả lời tốt đẹp. Mục đích của lưới là tạo lưới bằng cách sử dụng tọa độ của mỗi độ mờ.
Cậu bé ngoan

1
Điều tôi thấy hơi lạ là các giá trị x và y được trả về riêng thay vì được kết hợp thành một mảng. Nếu tôi muốn chúng trong một mảng, tôi cần phải làm:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892

64

Trên thực tế mục đích np.meshgridđã được đề cập trong tài liệu:

np.meshgrid

Trả về ma trận tọa độ từ các vectơ tọa độ.

Tạo các mảng tọa độ ND cho các đánh giá được vector hóa của các trường vô hướng / vectơ ND trên các lưới ND, được đưa ra các mảng tọa độ một chiều x1, x2, ..., xn.

Vì vậy, mục đích chính của nó là tạo ra ma trận tọa độ.

Có lẽ bạn chỉ tự hỏi:

Tại sao chúng ta cần tạo ma trận tọa độ?

Lý do bạn cần ma trận tọa độ với Python / NumPy là vì không có mối quan hệ trực tiếp từ tọa độ đến giá trị, ngoại trừ khi tọa độ của bạn bắt đầu bằng 0 và hoàn toàn là số nguyên dương. Sau đó, bạn chỉ có thể sử dụng các chỉ số của một mảng làm chỉ mục. Tuy nhiên, khi đó không phải là trường hợp bạn cần lưu trữ tọa độ cùng với dữ liệu của mình. Đó là nơi lưới điện đi vào.

Giả sử dữ liệu của bạn là:

1  2  1
2  5  2
1  2  1

Tuy nhiên, mỗi giá trị đại diện cho một vùng rộng 2 km theo chiều ngang và 3 km theo chiều dọc. Giả sử nguồn gốc của bạn là góc trên bên trái và bạn muốn các mảng biểu thị khoảng cách bạn có thể sử dụng:

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

trong đó v là:

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

và h:

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

Vì vậy, nếu bạn có hai chỉ số, giả sử xy(đó là lý do tại sao giá trị trả về meshgridthường là xxhoặc xsthay vì xtrong trường hợp này tôi chọn htheo chiều ngang!) Thì bạn có thể lấy tọa độ x của điểm, tọa độ y của điểm và giá trị tại thời điểm đó bằng cách sử dụng:

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

Điều đó giúp việc theo dõi tọa độ dễ dàng hơn nhiều (thậm chí quan trọng hơn) bạn có thể chuyển chúng đến các hàm cần biết tọa độ.

Một lời giải thích dài hơn một chút

Tuy nhiên, np.meshgridbản thân nó không thường được sử dụng trực tiếp, hầu hết chỉ sử dụng một trong những đối tượng tương tựnp.mgrid hoặc np.ogrid. Dưới đây np.mgridđại diện cho sparse=Falsenp.ogridcác sparse=Truetrường hợp (tôi tham khảo các sparseđối số của np.meshgrid). Lưu ý rằng có một sự khác biệt đáng kể giữa np.meshgridnp.ogridnp.mgrid: Hai giá trị được trả về đầu tiên (nếu có hai hoặc nhiều hơn) được đảo ngược. Thường thì điều này không quan trọng nhưng bạn nên đặt tên biến có ý nghĩa tùy thuộc vào ngữ cảnh.

Ví dụ, trong trường hợp lưới 2D và matplotlib.pyplot.imshowviệc đặt tên cho mục được trả lại đầu tiên np.meshgrid xvà thứ hai trong ykhi đó là cách khác để tìm np.mgridnp.ogrid.

np.ogrid và lưới thưa thớt

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

Như đã nói, đầu ra bị đảo ngược khi so sánh với np.meshgrid, đó là lý do tại sao tôi giải nén nó yy, xxthay vì 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]])

Điều này đã trông giống như tọa độ, cụ thể là các đường x và y cho các ô 2D.

Hình dung:

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

nhập mô tả hình ảnh ở đây

np.mgrid và lưới điện dày đặc

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

Áp dụng tương tự ở đây: Đầu ra được đảo ngược so với 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]])

Không giống như ogridcác mảng này chứa tất cả xxyytọa độ trong -5 <= xx <= 5; -5 <= yy <= 5 lưới.

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

nhập mô tả hình ảnh ở đây

Chức năng

Không chỉ giới hạn ở 2D, các hàm này hoạt động cho các kích thước tùy ý (tốt, có số lượng đối số tối đa được cung cấp cho hàm trong Python và số lượng kích thước tối đa mà NumPy cho phép):

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

Ngay cả khi chúng cũng hoạt động cho 1D, có hai hàm tạo lưới 1D (phổ biến hơn nhiều):

Bên cạnh startstopđối số, nó cũng hỗ trợ stepđối số (thậm chí các bước phức tạp đại diện cho số bước):

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

Các ứng dụng

Bạn đặc biệt hỏi về mục đích và trên thực tế, các lưới này cực kỳ hữu ích nếu bạn cần một hệ tọa độ.

Ví dụ: nếu bạn có hàm NumPy tính toán khoảng cách theo hai chiều:

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

Và bạn muốn biết khoảng cách của từng điểm:

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

Đầu ra sẽ giống hệt nhau nếu một trong một lưới dày đặc thay vì lưới mở. Phát sóng NumPys làm cho nó có thể!

Hãy hình dung kết quả:

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

nhập mô tả hình ảnh ở đây

Và đây cũng là khi NumPys mgridogridtrở nên rất thuận tiện vì nó cho phép bạn dễ dàng thay đổi độ phân giải của lưới:

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

nhập mô tả hình ảnh ở đây

Tuy nhiên, vì imshowkhông hỗ trợ xyđầu vào nên người ta phải thay đổi dấu tích bằng tay. Sẽ thật sự thuận tiện nếu nó chấp nhận xytọa độ, phải không?

Thật dễ dàng để viết các hàm với NumPy xử lý một cách tự nhiên với các lưới. Hơn nữa, có một số chức năng trong NumPy, SciPy, matplotlib mong bạn vượt qua trong lưới.

Tôi thích hình ảnh vì vậy hãy khám phá 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)

nhập mô tả hình ảnh ở đây

Lưu ý cách tọa độ đã được đặt chính xác! Đó sẽ không phải là trường hợp nếu bạn vừa thông qua density.

Hoặc để đưa ra một ví dụ thú vị khác bằng cách sử dụng các mô hình astropy (lần này tôi không quan tâm nhiều đến tọa độ, tôi chỉ sử dụng chúng để tạo một số lưới):

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)

nhập mô tả hình ảnh ở đây

Mặc dù đó chỉ là "cho ngoại hình" một số chức năng liên quan đến mô hình chức năng và phù hợp (ví dụ scipy.interpolate.interp2d, scipy.interpolate.griddatathậm chí hiển thị ví dụ sử dụng np.mgrid) trong scipy vv yêu cầu lưới. Hầu hết trong số này hoạt động với lưới mở và lưới dày đặc, tuy nhiên một số chỉ hoạt động với một trong số chúng.


Tôi chỉ muốn nói một lời cảm ơn rất lớn cho câu trả lời cực kỳ chi tiết này. Điều này làm cho ngày của tôi.
Jlanger

Thật là một cách hay để trả lời một câu hỏi .... rất chi tiết. Cảm ơn bạn
Bipin

h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- kể từ 2km ngang và 3km dọc, phạm vi đầu tiên có nên nhân 2 và 2 với 3 không?
Nixt

@Nixt Thật không may, nó không đơn giản như vậy. Tôi có thể phải kiểm tra lại phần đó của câu trả lời. Đó là sự đánh đổi giữa hiển thị chuyển đổi của ma trận và lập chỉ mục đảo ngược - thông thường bạn mong đợi chỉ số đầu tiên là ngang và dọc thứ hai nhưng sau đó màn hình sẽ được chuyển đổi. Tuy nhiên, đây chủ yếu là một chi tiết hy vọng không làm mất hiệu lực bản chất của câu trả lời nhằm minh họa lý do cho lưới điện. Nhưng tôi sẽ cố gắng sửa lại điều này vào một ngày trong tương lai.
MSeifert

36

Giả sử bạn có một chức năng:

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

và bạn muốn, ví dụ, để xem nó trông như thế nào trong phạm vi 0 đến 2 * pi. Bạn sẽ làm điều này như thế nào? Có 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

và một cốt truyện như vậy sẽ như thế nào:

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

nhập mô tả hình ảnh ở đây

Vì vậy, np.meshgridchỉ là một tiện lợi. Về nguyên tắc, điều tương tự có thể được thực hiện bởi:

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

nhưng ở đó bạn cần nhận thức được kích thước của mình (giả sử bạn có nhiều hơn hai ...) và phát sóng đúng. np.meshgridlàm tất cả điều này cho bạn.

Ngoài ra, lướigrid cho phép bạn xóa tọa độ cùng với dữ liệu nếu bạn muốn thực hiện phép nội suy nhưng loại trừ các giá trị nhất định:

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

Vì vậy, làm thế nào bạn sẽ làm nội suy bây giờ? Bạn có thể cung cấp xycho một hàm nội suy như scipy.interpolate.interp2dvậy, vì vậy bạn cần một cách để biết tọa độ nào đã bị xóa:

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

và sau đó bạn vẫn có thể nội suy với tọa độ "đúng" (hãy thử nó mà không có lướigrid và bạn sẽ có rất nhiều mã bổ sung):

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

và lướigrid gốc cho phép bạn lấy lại phép nội suy trên lưới ban đầu:

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

Đây chỉ là một số ví dụ mà tôi đã sử dụng meshgridcó thể có nhiều hơn nữa.


1
Cảm ơn bạn vì câu trả lời! Các khó hiểu thời điểm nhất đối với tôi là trở lại giá trị xx, yy. Thật khó để hiểu chúng là gì và tại sao chúng ta sử dụng chúng để tính toán hàm. Có vẻ, tôi đã nhận nó. Chúng tôi muốn tính toán một số chức năng dựa trên tọa độ. Chúng ta có thể viết một cái gì đó như thế này: for x=1:10: for y=1:10: z[x,y]=sin(x)+sin(y)Thay vào đó chúng ta tính toán ztheo một cách khác z=sin([x,x,...,x]) + sin([y,y,..y]). Đúng nếu tôi đã sai lầm!
Alena Kastsiukavets

Đó không phải là mã giả chính xác 100%, nhưng tôi hy vọng bạn thấy quan điểm của tôi)
Alena Kastsiukavets

Trên thực tế bạn luôn cần vòng lặp kép (mã đầu tiên của bạn). Nhưng có nhiều cách khác nhau để lưu trữ nó với numpy: lướigrid hoặc phát sóng. Nếu bạn không loại bỏ điểm (xem phần cuối câu trả lời của tôi) thì cả hai đều thực sự tương đương về chức năng. Phát sóng chỉ là một vòng lặp ngầm trên kích thước được phát sóng. Lưu ý rằng tôi đã sử dụng [:,None][None, :]bao gồm các kích thước bổ sung để kết quả phát chính xác. Ví dụ thứ hai của bạn giống như:sin([[y],[y],..[y]])
MSeifert

Một minh họa thực sự tốt đẹp. Cảm ơn vì đã nỗ lực rất nhiều.
natersoz

interpolated_grid = interpolated(xx, yy)- điều này không hiệu quả với tôi, lỗi:x and y should both be 1-D arrays
Nixt

4

Gridgrid giúp tạo lưới hình chữ nhật từ hai mảng 1-D của tất cả các cặp điểm từ hai mảng.

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

Bây giờ, nếu bạn đã xác định hàm f (x, y) và bạn muốn áp dụng hàm này cho tất cả các kết hợp điểm có thể có từ các mảng 'x' và 'y', thì bạn có thể làm điều này:

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

Giả sử, nếu chức năng của bạn chỉ tạo ra sản phẩm của hai yếu tố, thì đây là cách có thể đạt được một sản phẩm cartesian, hiệu quả cho các mảng lớn.

Giới thiệu từ đây


1

Ý kiến ​​cơ bản

Cho các giá trị x có thể xs, (nghĩ về chúng như các dấu tick trên trục x của một âm mưu) và các giá trị y có thể ys, meshgridtạo ra tập hợp các điểm lưới (x, y) tương ứng --- tương tự set((x, y) for x in xs for y in yx). Ví dụ: nếu xs=[1,2,3]ys=[4,5,6], chúng ta sẽ có được bộ tọa độ {(1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (1,6), (2,6), (3,6)}.

Hình thức của giá trị hoàn trả

Tuy nhiên, biểu diễn meshgridtrả về khác với biểu thức trên theo hai cách:

Đầu tiên , meshgridđặt ra các điểm lưới trong một mảng 2d: các hàng tương ứng với các giá trị y khác nhau, các cột tương ứng với các giá trị x khác nhau --- như trong list(list((x, y) for x in xs) for y in ys), sẽ đưa ra mảng sau:

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

Thứ hai , meshgridtrả về các tọa độ x và y riêng biệt (nghĩa là trong hai mảng 2d numpy khác nhau):

   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

Lưu ý, np.meshgridcũng có thể tạo lưới cho kích thước cao hơn. Cho xs, ys và zs, bạn sẽ nhận lại xcoords, ycoords, zcoords dưới dạng mảng 3d. meshgridcũng hỗ trợ thứ tự đảo ngược của kích thước cũng như biểu diễn thưa thớt của kết quả.

Các ứng dụng

Tại sao chúng ta muốn hình thức đầu ra này?

Áp dụng một hàm tại mọi điểm trên lưới: Một động lực là các toán tử nhị phân như (+, -, *, /, **) bị quá tải cho các mảng numpy như các hoạt động theo nguyên tố. Điều này có nghĩa là nếu tôi có một hàm def f(x, y): return (x - y) ** 2hoạt động trên hai vô hướng, tôi cũng có thể áp dụng nó trên hai mảng numpy để có được một mảng các kết quả theo nguyên tố: ví dụ f(xcoords, ycoords)hoặc f(*np.meshgrid(xs, ys))đưa ra như sau trong ví dụ trên:

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

Sản phẩm bên ngoài chiều cao hơn: Tôi không chắc cách này hiệu quả, nhưng bạn có thể nhận được các sản phẩm bên ngoài chiều cao theo cách này : np.prod(np.meshgrid([1,2,3], [1,2], [1,2,3,4]), axis=0).

Các đường đồng mức trong matplotlib: Tôi tình cờ thấy meshgridkhi điều tra vẽ các đường đồng mức với matplotlib để vẽ các ranh giới quyết định . Đối với điều này, bạn tạo lưới với meshgrid, đánh giá hàm tại mỗi điểm lưới (ví dụ như được hiển thị ở trên), sau đó chuyển xcoords, ycoords và tính giá trị f (ví dụ zcoords) vào hàm contourf.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.