0

I'm trying to create a grid of coordinates for an algorithm that requires and understanding of distance. I know how to do this for a known number of dimensions - like so for 2D:

x = [0,1,2]
y = [10,11,12]


z = np.zeros((3,3,2))
for i,X in enumerate(x):
    for j,Y in enumerate(y):
        z[i][j][0] = X
        z[i][j][1] = Y
print(z)
--------------------------
array([[[  0.,  10.],
        [  0.,  11.],
        [  0.,  12.]],

       [[  1.,  10.],
        [  1.,  11.],
        [  1.,  12.]],

       [[  2.,  10.],
        [  2.,  11.],
        [  2.,  12.]]])

This works well enough. I end up with a shape of (3,3,2) where the 2 is the values of the coordinates at that point. I'm trying to use this to create a probability surface, so I need to be able to have each point be it's own "location" value. Is there a way to easily extend this into N-dimensions? There I would have an unknown number of for loops. Due to project constraints I have access to Python built-ins and numpy, but that's more or less it.

I've tried np.meshgrid() but it results in an output shape of (2,3,3) and my attempts to reshape it never give me the coordinates in the correct order. Any ideas on how I could do this cleanly?

8
  • By N do you mean the number of arrays? For example, in the sample case you have two arrays, so it's 2-dimensional? Commented Oct 28, 2017 at 16:09
  • Maybe this is what you're looking for: xarray Commented Oct 28, 2017 at 16:17
  • @Divakar By N - I mean a user is going to put in some matrix of data and however many columns there are will be N. So if they have 8 columns of data, I need an 8-dimensional grid. Commented Oct 28, 2017 at 16:30
  • Hey @sharatpc. I'll take a look into that. Thanks! Commented Oct 28, 2017 at 16:31
  • If I got that right - With e.g. 8 columns of data in x , y, assuming they stay 1D, the code stays the same, right? So, what's the issue? Commented Oct 28, 2017 at 16:33

1 Answer 1

1

I can replicate your z with

In [223]: np.stack([np.tile([x],(1,3)).reshape(3,3).T,np.tile([y],(3,1))],2)
Out[223]: 
array([[[ 0, 10],
        [ 0, 11],
        [ 0, 12]],

       [[ 1, 10],
        [ 1, 11],
        [ 1, 12]],

       [[ 2, 10],
        [ 2, 11],
        [ 2, 12]]])

The tile pieces look like

In [224]: np.tile([y],(3,1))
Out[224]: 
array([[10, 11, 12],
       [10, 11, 12],
       [10, 11, 12]])
In [225]: np.tile([x],(1,3)).reshape(3,3).T
Out[225]: 
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2]])

I might be able clean up the 2nd one. But the basic idea is to replicate the inputs in such a way that stack can combine them into the desired (n,n,2) array.

Once this is understood, it shouldn't be hard to extend things to 3d and up. But I haven't fully processed your intentions.

Possibly simpler (and repeat is faster than tile):

np.stack([np.repeat(x,3).reshape(3,3), np.repeat(y,3).reshape(3,3).T], 2)

With more dimensions the transpose might require refinement.


Same thing with meshgrid (it probably uses repeat or tile internally:

In [232]: np.stack(np.meshgrid(x,y, indexing='ij'),2)
Out[232]: 
array([[[ 0, 10],
        [ 0, 11],
        [ 0, 12]],

       [[ 1, 10],
        [ 1, 11],
        [ 1, 12]],

       [[ 2, 10],
        [ 2, 11],
        [ 2, 12]]])

In higher dimensions:

In [237]: np.stack(np.meshgrid([1,2], [10,20,30], [100,200,300,400], indexing='ij'), 3).sum(axis=-1)
Out[237]: 
array([[[111, 211, 311, 411],
        [121, 221, 321, 421],
        [131, 231, 331, 431]],

       [[112, 212, 312, 412],
        [122, 222, 322, 422],
        [132, 232, 332, 432]]])
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.