Какова цель сетки в Python / NumPy?

303

Может кто-нибудь объяснить мне, какова цель meshgridфункции в Numpy? Я знаю, что это создает какую-то сетку координат для построения графиков, но я не вижу прямой выгоды от этого.

Я изучаю «Машинное обучение Python» у Себастьяна Рашки, и он использует его для построения границ решения. Смотрите ввод 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)

Пожалуйста, если возможно, также покажите мне много реальных примеров.

HonzaB
источник

Ответы:

391

Цель meshgridсостоит в том, чтобы создать прямоугольную сетку из массива значений x и массива значений y.

Так, например, если мы хотим создать сетку, в которой у нас есть точка при каждом целочисленном значении между 0 и 4 в направлениях x и y. Для того, чтобы создать прямоугольную сетку, мы должны каждую комбинацию из xи yточек.

Это будет 25 очков, верно? Так что, если мы хотим создать й и у массива для всех этих точек, мы могли бы сделать следующее.

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)) по диапазону значений для xи y.

Поскольку эта функция была выбрана на прямоугольной сетке, функцию теперь можно визуализировать как «изображение».

введите описание изображения здесь

Кроме того, теперь результат можно передать функциям, которые ожидают данные в прямоугольной сетке (т.е. contourf)

Suever
источник
10
Вы не объяснили возвращаемые значения xxи yy. Для меня загадочной частью было то, почему он возвращает ту пару результатов и как они выглядят. Ответ Хай Фана удобен для этого. Я полагаю, это сделано для удобства, так как plot хочет два таких параметра.
nealmcb
2
Я не знаю - вот почему я ищу эту информацию;) Так что я не говорю, что она должна возвращать что-то другое. Я просто высказываю предположение о недостающей части информации для тех, кто только что прочитал принятый ответ. И если хотите, я предлагаю, чтобы ваш ответ (который уже очень хорош - спасибо!) Был бы немного более полным, если бы вы объяснили возвращаемые значения (как это сделал Хай) для тех из нас, кто все еще озадачен.
nealmcb
1
Чтобы лучше понять значения xx и yy, рассмотрим утверждение, что следующий код дает вам тот же результат, что и np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Мэтт
1
Этот ответ сбивает с толку - не ваша первая иллюстрация xи yназад? Когда вы делаете xx, yy = np.meshgrid(np.arange(4), np.arange(4)), это обратное тому, что у вас есть, xи yв первой части ответа. Он соответствует порядку выходных данных для mgrid, но не для сетки. Значение xxдолжно увеличиваться в направлении x, а ваше - в направлении y.
Скотт Станевич
1
@ScottStaniewicz Спасибо за указание, что наши, теперь уверены, как я испортил это ... Обновлено!
Suever
250

Предоставлено Microsoft Excel: 

введите описание изображения здесь

сарсапарель
источник
6
Ницца. FWIW, если вы хотите массив 2 х 12 пар в середине:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
ДЕНИС
5
и если вы хотите массив пар 12 х 2 посередине:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn
2
Хороший ответ. Цель meshgrid - создать сетку, используя координаты каждого затемнения.
Хороший мальчик
1
Что я нахожу немного странным, так это то, что значения x и y возвращаются отдельно, а не объединяются в один массив. Если я хочу, чтобы они были в одном массиве, мне нужно сделать:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892
66

На самом деле цель np.meshgridуже упоминается в документации:

np.meshgrid

Вернуть координатные матрицы из координатных векторов.

Создайте ND координатные массивы для векторизованных вычислений ND скалярных / векторных полей над 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]])

и ч:

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.ogridв sparse=Trueслучае (я ссылаться на sparseаргумент np.meshgrid). Обратите внимание, что между np.meshgridand np.ogridи есть существенная разница np.mgrid: первые два возвращаемых значения (если их два или более) меняются местами. Часто это не имеет значения, но вы должны давать значимые имена переменных в зависимости от контекста.

Например, в случае двумерной сетки matplotlib.pyplot.imshowимеет смысл назвать первый возвращаемый элемент np.meshgrid xи второй, в yто время как для np.mgridи наоборот np.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, эти функции работают для произвольных измерений (ну, в Python есть максимальное количество аргументов для функции и максимальное количество измерений, которое допускает 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.

Даже если они также работают для 1D, есть две (гораздо более распространенные) функции создания сетки 1D:

Помимо аргумента startand 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 и т. Д., Требуют сеток. Большинство из них работают с открытыми сетками и плотными сетками, однако некоторые работают только с одним из них.

MSeifert
источник
Я просто хочу сказать огромное спасибо за этот чрезвычайно подробный ответ. Это сделало мой день.
Jlanger
Какой прекрасный способ ответить на вопрос .... так подробно. Спасибо
Бипин
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- поскольку его 2 км по горизонтали и 3 км по вертикали, не следует ли умножить первый диапазон на 2, а второй на 3?
Nixt
@Nixt К сожалению, не все так просто. Возможно, мне придется проверить эту часть ответа снова. Это компромисс между транспонированным отображением матрицы и обратным индексированием - обычно вы ожидаете, что первый индекс будет горизонтальным, а второй - вертикальным, но тогда дисплей будет транспонирован. Тем не менее, это в основном деталь, которая, надеюсь, не лишает смысла суть ответа, который призван проиллюстрировать причину появления сеток. Но я постараюсь пересмотреть это в будущем.
Мейферт
36

Предположим, у вас есть функция:

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

и вы хотите, например, посмотреть, как это выглядит в диапазоне от 0 до 2 * пи. Как бы вы это сделали? Там 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]

и тогда вы все еще можете интерполировать с «правильными» координатами (попробуйте без сетки, и у вас будет много дополнительного кода):

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

и оригинальная сетка позволяет вам снова получить интерполяцию на исходной сетке:

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

Это всего лишь несколько примеров, где я использовал, meshgridможет быть гораздо больше.

MSeifert
источник
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]). Поправь меня, если я ошибаюсь!
Алена Костюкавец
Это не на 100% правильный псевдокод, но я надеюсь, что вы понимаете мою точку зрения)
Алена Касцюкавец
На самом деле вам всегда нужен двойной цикл (ваш первый код). Но есть разные способы архивирования numpy: с помощью сетки или трансляции. Если вы не отбрасываете баллы (см. Последнюю часть моего ответа), то оба на самом деле функционально эквивалентны. Вещание - это просто неявный цикл в измерении, которое будет транслироваться. Обратите внимание, что я использовал [:,None]и [None, :]включить дополнительные измерения, чтобы результат транслировался правильно. Ваш второй пример больше похож на:sin([[y],[y],..[y]])
MSeifert
Действительно хорошая иллюстрация. Спасибо за то, что приложили столько усилий.
натерсоз
interpolated_grid = interpolated(xx, yy)- это не работает для меня, ошибка:x and y should both be 1-D arrays
Nixt
4

Сетка mesh помогает создать прямоугольную сетку из двух одномерных массивов всех пар точек из двух массивов.

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 отдельно (т. Е. В двух разных двухмерных массивах 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 в виде трехмерных массивов. meshgridтакже поддерживает обратный порядок размеров, а также разреженное представление результата.

Приложения

Зачем нам нужна эта форма вывода?

Примените функцию в каждой точке сетки: одна из причин состоит в том, что бинарные операторы, такие как (+, -, *, /, **), перегружаются для массивов с пустыми данными как элементарные операции. Это означает, что, если у меня есть функция, def f(x, y): return (x - y) ** 2которая работает с двумя скалярами, я также могу применить ее к двум массивам, чтобы получить массив поэлементных результатов: например, 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.

user3780389
источник