How to define a 2D array of (x,y) coordinates

Question:

I have a 2d space of (x,y) coordinates that I want to model in python and want to know a way to define the 2d space in python where I can assign multiple values to a point (x,y). Later values at coordinates will be changed based on some coordinate dependent calculations.

I thought about using numpy array to create the 2d array based on the size entered by the user. I started by creating a 2d n*m numpy array of zeros and later parts of the code calculations are done on points. But in this way each point (x,y) only has one value.

import numpy as np

x_coor=135

y_coor=120

grid=np.zeros((x_coor,y_coor)

Is there a way to make it grid[x,y]=(value1,value2), and is there a better way to define the grid other than a numpy array?

Asked By: ironmacaron

||

Answers:

You could indeed use numpy for this. One way would be to define a 3d array as np.zeros((x_coor, y_coor, 2)) and save each of the coordinates along the last axis.

Another way to obtain the desired structure using numpy could be to define an ndarray of tuples, and uptade each point in the mentioned fashion, i.e. grid[x,y] = (value1,value2). Here’s how you could do it:

x_coor=135
y_coor=120

grid = np.zeros((5,3), dtype='i,i')
grid[0,0] = (1,2)
grid[2,2] = (5,1)
grid[1,0] = (3,5)

print(grid)
array([[(1, 2), (0, 0), (0, 0)],
       [(3, 5), (0, 0), (0, 0)],
       [(0, 0), (0, 0), (5, 1)],
       [(0, 0), (0, 0), (0, 0)],
       [(0, 0), (0, 0), (0, 0)]], dtype=[('f0', '<i4'), ('f1', '<i4')])

If you want to update several values at once using multiple coordinates you could do:

grid = np.zeros((5,3), dtype='i,i')

coordinates = np.array([(1,2),(2,2), (0,0)], dtype='i,i')
new_vals = np.array([(12,2),(4,1), (0,9)], dtype='i,i')

grid[tuple(zip(*coordinates))] = new_vals

print(grid)
array([[( 0, 9), ( 0, 0), ( 0, 0)],
       [( 0, 0), ( 0, 0), (12, 2)],
       [( 0, 0), ( 0, 0), ( 4, 1)],
       [( 0, 0), ( 0, 0), ( 0, 0)],
       [( 0, 0), ( 0, 0), ( 0, 0)]], dtype=[('f0', '<i4'), ('f1', '<i4')])

Do note though that tuples are inmutable, so if you’re planning to perform operations with these coordinates you should go with the first approach.

Answered By: yatu

Short answer to your question: you should use pandas instead of a numpy array. Numpy is designed to speed up array calculations, and so it does not permit defining each element of an array as a list. Pandas dataframes however do permit these type of operations. Here is how you would do such an operation in pandas, and note especially how the original dataframe is defined flexibly so that it can be later manipulated to change the length of the lists contained in each cell:

import numpy as np
import pandas as pd
df = pd.DataFrame(columns=[0,1,2])

for i in range(5):
df.loc[i,0] = np.arange(i)
df.loc[i,1] = np.arange(i)
df.loc[i,2] = np.arange(i)

print(df.loc[2,2])

This is the entry in cell (2,2):

array([0, 1])

Which you can change now as you need:

df.loc[2,2] = [10,20,30]

So now:

print(df.loc[2,2])

gives you:

[10, 20, 30]
Answered By: HMReliable

I’m not sure your application, but another math-inspired solution is to store 2d coordinates as numpy’s complex numbers. These store a FP double for real and imaginary coordinates, which can be accessed with np.real and np.imag. This also makes it easy to subtract complex numbers and compute Euclidean distances as absolute value.

a = np.zeros((3, 3), dtype=np.cfloat)
a[2,2] = 1 + 1j
Answered By: qwr