I have a grid of points, that look something like this, the points represent the bottom left corner of an area and I want to retrieve that grid. I've tried doing this and it's not working, the resulting grid has overlapping squares when it shouldn't have.
def transform_to_grid(mesh, origin="bottom-left"):
mesh.sort_values(by=["i_lat", "i_lon"], inplace=True)
xmax=mesh["i_lon"].max()
ymax=mesh["i_lat"].max()
mesh_max=mesh[(mesh["i_lat"]==ymax) & (mesh["i_lon"]==xmax)]
mesh_min=mesh[(mesh["i_lat"]==0) & (mesh["i_lon"]==0)]
xmin=0
ymin=0
## i_lat increases from south to north.
if mesh_max["lat"].values[0]>mesh_min["lat"].values[0]:
Bool_StoN=True
ysteps=np.arange(ymin, ymax, 1)
else:
Bool_StoN=False
ysteps=np.arange(ymax, ymin, -1)
## i_lon increases from left to right.
if mesh_max["lon"].values[0]>mesh_min["lon"].values[0]:
BoolLtoR=True
xsteps=np.arange(xmin, xmax, 1)
else:
BoolLtoR=False
xsteps=np.arange(xmax, xmin, -1)
center=[]
grid_cells = []
info0 = mesh[(mesh["i_lat"]==ysteps[0]) & (mesh["i_lon"]==xsteps[0])]
x0 = info0.lon.values[0]
y0 = info0.lat.values[0]
for x in range(1, xmax):
for y in range(1, ymax):
## Bounds
info=mesh[(mesh["i_lat"]==ysteps[y]) & (mesh["i_lon"]==xsteps[x])]
x1 = info.lon.values[0]
y1 = info.lat.values[0]
## Append information
grid_cells.append( box(x0, y0, x1, y1) )
if origin=="bottom-left":
center.append((ysteps[y-1], xsteps[x-1]))
elif origin=="bottom-right":
center.append((ysteps[y-1], xsteps[x]))
elif origin=="top-right":
center.append((ysteps[y], xsteps[x]))
elif origin=="top-left":
center.append((ysteps[y], xsteps[x-1]))
y0=y1
x0=x1
cell = gpd.GeoDataFrame({"geometry":grid_cells, "indexes":center}, crs="epsg:4326")
return cell.merge(mesh[["lat", "lon", "indexes"]], on="indexes", how="inner")
grid=transform_to_grid(mesh, origin="bottom-left")
mesh=
lat lon i_lat i_lon geometry
0 -31.765354 -71.461792 0 0 POINT (-71.46179 -31.76535)
1 -31.767292 -71.149109 0 1 POINT (-71.14911 -31.76729)
2 -31.768250 -70.836365 0 2 POINT (-70.83636 -31.76825)
3 -31.768250 -70.523621 0 3 POINT (-70.52362 -31.76825)
4 -31.767292 -70.210907 0 4 POINT (-70.21091 -31.76729)
.. ... ... ... ... ...
79 -30.167404 -69.302917 6 7 POINT (-69.30292 -30.16740)
80 -30.162682 -68.996948 6 8 POINT (-68.99695 -30.16268)
81 -30.157040 -68.691040 6 9 POINT (-68.69104 -30.15704)
82 -30.150452 -68.385193 6 10 POINT (-68.38519 -30.15045)
83 -30.142902 -68.079407 6 11 POINT (-68.07941 -30.14290)
I am very confused as to why the code doesn't work. I am going from south to north and west to east in the loop, keeping the older lat,lon
pair to create the polygon.
What I need to do is basically connect the points (that are not equally spaced) and retrieve the square grid from there.
Best Answer
This is a fairly efficient implementation, using (fully vectorized) numpy operations:
I'm using a
lexsort
the get the proper ordering (by rows and columns): this might go wrong if your points are located on a very curvilinear grid. In that case, you'd probably need to project to a Cartesian coordinate system first (with e.g. pyproj).