Numpy meshgrid в 3D - PullRequest
       40

Numpy meshgrid в 3D

40 голосов
/ 01 декабря 2009

Сетка Numpy очень полезна для преобразования двух векторов в координатную сетку. Какой самый простой способ расширить это до трех измерений? Поэтому, учитывая три вектора x, y и z, создайте массивы 3x3D (вместо массивов 2x2D), которые можно использовать в качестве координат.

Ответы [ 6 ]

42 голосов
/ 27 марта 2014

Numpy (по состоянию на 1,8, я думаю) теперь поддерживает более высокую, чем 2D генерацию координатных сеток с meshgrid . Одно важное дополнение, которое действительно помогло мне, - это возможность выбрать порядок индексации (либо xy, либо ij для декартовой или матричной индексации соответственно), что я проверил на следующем примере:

import numpy as np

x_ = np.linspace(0., 1., 10)
y_ = np.linspace(1., 2., 20)
z_ = np.linspace(3., 4., 30)

x, y, z = np.meshgrid(x_, y_, z_, indexing='ij')

assert np.all(x[:,0,0] == x_)
assert np.all(y[0,:,0] == y_)
assert np.all(z[0,0,:] == z_)
29 голосов
/ 02 декабря 2009

Вот исходный код сетки:

def meshgrid(x,y):
    """
    Return coordinate matrices from two coordinate vectors.

    Parameters
    ----------
    x, y : ndarray
        Two 1-D arrays representing the x and y coordinates of a grid.

    Returns
    -------
    X, Y : ndarray
        For vectors `x`, `y` with lengths ``Nx=len(x)`` and ``Ny=len(y)``,
        return `X`, `Y` where `X` and `Y` are ``(Ny, Nx)`` shaped arrays
        with the elements of `x` and y repeated to fill the matrix along
        the first dimension for `x`, the second for `y`.

    See Also
    --------
    index_tricks.mgrid : Construct a multi-dimensional "meshgrid"
                         using indexing notation.
    index_tricks.ogrid : Construct an open multi-dimensional "meshgrid"
                         using indexing notation.

    Examples
    --------
    >>> X, Y = np.meshgrid([1,2,3], [4,5,6,7])
    >>> X
    array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]])
    >>> Y
    array([[4, 4, 4],
           [5, 5, 5],
           [6, 6, 6],
           [7, 7, 7]])

    `meshgrid` is very useful to evaluate functions on a grid.

    >>> x = np.arange(-5, 5, 0.1)
    >>> y = np.arange(-5, 5, 0.1)
    >>> xx, yy = np.meshgrid(x, y)
    >>> z = np.sin(xx**2+yy**2)/(xx**2+yy**2)

    """
    x = asarray(x)
    y = asarray(y)
    numRows, numCols = len(y), len(x)  # yes, reversed
    x = x.reshape(1,numCols)
    X = x.repeat(numRows, axis=0)

    y = y.reshape(numRows,1)
    Y = y.repeat(numCols, axis=1)
    return X, Y

Это довольно просто понять. Я расширил шаблон до произвольного числа измерений, но этот код ни в коем случае не оптимизирован (и не полностью проверен на ошибки), но вы получаете то, за что платите. Надеюсь, это поможет:

def meshgrid2(*arrs):
    arrs = tuple(reversed(arrs))  #edit
    lens = map(len, arrs)
    dim = len(arrs)

    sz = 1
    for s in lens:
        sz*=s

    ans = []    
    for i, arr in enumerate(arrs):
        slc = [1]*dim
        slc[i] = lens[i]
        arr2 = asarray(arr).reshape(slc)
        for j, sz in enumerate(lens):
            if j!=i:
                arr2 = arr2.repeat(sz, axis=j) 
        ans.append(arr2)

    return tuple(ans)
7 голосов
/ 01 декабря 2009

Можете ли вы показать нам, как вы используете np.meshgrid? Очень велика вероятность того, что вам действительно не нужна meshgrid, потому что numy широковещание может делать то же самое без генерации повторяющегося массива.

Например,

import numpy as np

x=np.arange(2)
y=np.arange(3)
[X,Y] = np.meshgrid(x,y)
S=X+Y

print(S.shape)
# (3, 2)
# Note that meshgrid associates y with the 0-axis, and x with the 1-axis.

print(S)
# [[0 1]
#  [1 2]
#  [2 3]]

s=np.empty((3,2))
print(s.shape)
# (3, 2)

# x.shape is (2,).
# y.shape is (3,).
# x's shape is broadcasted to (3,2)
# y varies along the 0-axis, so to get its shape broadcasted, we first upgrade it to
# have shape (3,1), using np.newaxis. Arrays of shape (3,1) can be broadcasted to
# arrays of shape (3,2).
s=x+y[:,np.newaxis]
print(s)
# [[0 1]
#  [1 2]
#  [2 3]]

Дело в том, что S=X+Y можно и нужно заменить на s=x+y[:,np.newaxis], потому что последний не требует (возможно, больших) повторяющихся массивов для формирования. Он также легко обобщается на более высокие размеры (больше осей). Вы просто добавляете np.newaxis там, где необходимо, чтобы осуществлять трансляцию по мере необходимости.

См. http://www.scipy.org/EricsBroadcastingDoc для более подробной информации о вещах с номерами.

5 голосов
/ 01 декабря 2009

Я думаю, что вы хотите

X, Y, Z = numpy.mgrid[-10:10:100j, -10:10:100j, -10:10:100j]

например.

4 голосов
/ 07 мая 2013

Вот многомерная версия meshgrid, которую я написал:

def ndmesh(*args):
   args = map(np.asarray,args)
   return np.broadcast_arrays(*[x[(slice(None),)+(None,)*i] for i, x in enumerate(args)])

Обратите внимание, что возвращаемые массивы являются представлениями исходных данных массива, поэтому изменение исходных массивов повлияет на массивы координат.

4 голосов
/ 03 марта 2012

Вместо написания новой функции numpy.ix_ должен делать то, что вы хотите.

Вот пример из документации:

>>> ixgrid = np.ix_([0,1], [2,4])
>>> ixgrid
(array([[0],
   [1]]), array([[2, 4]]))
>>> ixgrid[0].shape, ixgrid[1].shape
((2, 1), (1, 2))'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...