Home > Blockchain >  Why is meshgrid changing (x, y, z) order to (y, x, z)?
Why is meshgrid changing (x, y, z) order to (y, x, z)?

Time:10-17

I have 3 vectors:

u = np.array([0, 100, 200, 300]) #hundreds
v = np.array([0, 10, 20]) #tens
w = np.array([0, 1]) #units

Then I used np.meshgrid to sum u[i] v[j],w[k]:

x, y, z = np.meshgrid(u, v, w)
func1 = x   y   z

So, when (i,j,k)=(3,2,1), func1[i, j, k] should return 321, but I only get 321 if I put func1[2, 3, 1]. Why is it asking me for vector v before u? Should I use numpy.ix_ instead?

CodePudding user response:

From the meshgrid docs:

Notes
-----
This function supports both indexing conventions through the indexing
keyword argument.  Giving the string 'ij' returns a meshgrid with
matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing.
In the 2-D case with inputs of length M and N, the outputs are of shape
(N, M) for 'xy' indexing and (M, N) for 'ij' indexing.  In the 3-D case
with inputs of length M, N and P, outputs are of shape (N, M, P) for
'xy' indexing and (M, N, P) for 'ij' indexing. 

In [109]: U,V,W = np.meshgrid(u,v,w, sparse=True)
In [110]: U
Out[110]: 
array([[[  0],        # (1,4,1)
        [100],
        [200],
        [300]]])
In [111]: U V W
Out[111]: 
array([[[  0,   1],
        [100, 101],
        [200, 201],
        [300, 301]],

       [[ 10,  11],
        [110, 111],
        [210, 211],
        [310, 311]],

       [[ 20,  21],
        [120, 121],
        [220, 221],
        [320, 321]]])

The result is (3,4,2) array; This is the cartesian case described in the notes.

With the documented indexing change:

In [113]: U,V,W = np.meshgrid(u,v,w, indexing='ij',sparse=True)
In [114]: U.shape
Out[114]: (4, 1, 1)
In [115]: (U V W).shape
Out[115]: (4, 3, 2)

Which matches the ix_ that you wanted:

In [116]: U,V,W = np.ix_(u,v,w)
In [117]: (U V W).shape
Out[117]: (4, 3, 2)

You are welcome to use either. Or even np.ogrid as mentioned in the docs.

Or even the home-brewed broadcasting:

In [118]: (u[:,None,None] v[:,None] w).shape
Out[118]: (4, 3, 2)

Maybe the 2d layout clarifies the two coordinates:

In [119]: Out[111][:,:,0]
Out[119]: 
array([[  0, 100, 200, 300],          # u going across, x-axis
       [ 10, 110, 210, 310],
       [ 20, 120, 220, 320]])
In [120]: (u[:,None,None] v[:,None] w)[:,:,0]
Out[120]: 
array([[  0,  10,  20],              # u going down - rows
       [100, 110, 120],
       [200, 210, 220],
       [300, 310, 320]])

CodePudding user response:

For your indexing method, you need axis 0 to be the direction of increment of 1s, axis 1 to be for 10s, and axis 2 to be for 100s.

You can just transpose to swap the axes to suit your indexing method -

u = np.array([0, 100, 200, 300]) #hundreds
v = np.array([0, 10, 20, 30]) #tens
w = np.array([0, 1, 2, 3]) #units

x,y,z = np.meshgrid(w,v,u)

func1 = x   y   z

func1 = func1.transpose(2,0,1)
func1
           # axis 0 is 1s 
        #------------------>
array([[[  0,   1,   2,   3],
        [ 10,  11,  12,  13], #
        [ 20,  21,  22,  23], # Axis 1 is 10s
        [ 30,  31,  32,  33]],

       [[100, 101, 102, 103],      #
        [110, 111, 112, 113],      # Axis 2 is 100s
        [120, 121, 122, 123],      #
        [130, 131, 132, 133]],

       [[200, 201, 202, 203],
        [210, 211, 212, 213],
        [220, 221, 222, 223],
        [230, 231, 232, 233]],

       [[300, 301, 302, 303],
        [310, 311, 312, 313],
        [320, 321, 322, 323],
        [330, 331, 332, 333]]])

Testing this by indexing -

>> func1[2,3,1]
231

>> func1[3,2,1]
321
  • Related