1

I had the following code in shapely 1.8.5.post1 which was working but was throwing a warning:

import os
os.environ['USE_PYGEOS'] = '0'
import numpy as np
import geopandas as gpd
from shapely.geometry import Point

pointList = [
    Point(0,0,2),
    Point(0,1,2),
    Point(1,0,2)
]

gdf = gpd.GeoDataFrame(pointList, geometry=0)
gdf.rename_geometry('geometry',inplace=True)

c = np.stack(gdf.geometry.apply(np.array))

print(c)
>:
[[0. 0. 2.]
 [0. 1. 2.]
 [1. 0. 2.]]

and the warning:

 /usr/local/lib/python3.10/dist-packages/pandas/core/apply.py:1105: ShapelyDeprecationWarning:
  The array interface is deprecated and will no longer work in Shapely 2.0.
  Convert the '.coords' to a numpy array instead.
    return self.apply_standard()

Hence my question: how exactly could I apply the .coords method in this code to achieve the exact same result?

Because as is, in shapely 2.0.0, the output is not a numpy array:


print(c)
>:
[<POINT Z (0 0 2)> <POINT Z (0 1 2)> <POINT Z (1 0 2)>]

Also, gdf.geometry.apply(np.array) and gdf.geometry are giving the exact same result in Shapely 2.0.0, so applying np.array on the geometry doesn't seem to have any effect:

>: 
0    POINT Z (0.00000 0.00000 2.00000)
1    POINT Z (0.00000 1.00000 2.00000)
2    POINT Z (1.00000 0.00000 2.00000)
Name: geometry, dtype: geometry

4 Answers 4

3

You can call xyz directly instead of mapping to a function:

c = np.stack([gdf.geometry.x, gdf.geometry.y, gdf.geometry.z], axis=1)

print(c)
# array([[0., 0., 2.],
#        [0., 1., 2.],
#        [1., 0., 2.]])
1
  • Oh, this is great! My guess is that this probably runs significantly quicker than the other solutions proposed here because it doesn't rely on the apply method, which can be pretty slow at times. Good job =)
    – Felipe D.
    Jan 28, 2023 at 16:01
2

You can take your approach and bundle it into a lambda function instead of defining a whole new function:

c = np.stack(gdf.geometry.apply(lambda x: np.array(x.coords).ravel()))

print(c)
#array([[0., 0., 2.],
#       [0., 1., 2.],
#       [1., 0., 2.]])
2
  • I'm not a big fan of lambdas but this is a nice trick. I'm sad things became a little less pythonic than with the previous Shapely version. Jan 28, 2023 at 9:00
  • Yeah, and it just looks real ugly. I;d take a look at this other answer. It's pythonic and probably executes much faster than this one.
    – Felipe D.
    Jan 28, 2023 at 16:02
1

My current workaround in shapely 2.0.0:

def get_array(geom):
    if isinstance(geom, Point):
        arr = np.array(geom.coords).ravel()

    return arr


c = np.stack(gdf.geometry.apply(get_array))

print(c)
>:
[[0. 0. 2.]
 [0. 1. 2.]
 [1. 0. 2.]]

But I am not 100% satisfied with it because I have to create a custom function.

1

The standard and probably fastest way to do this using shapely 2 would be to use shapely.get_coordinates I think, like this:

import os
os.environ["USE_PYGEOS"] = "0"
import geopandas as gpd
import shapely
from shapely.geometry import Point

points = {"geometry": [Point(0, 0, 2), Point(0, 1, 2), Point(1, 0, 2)]}
gdf = gpd.GeoDataFrame(points)
c = shapely.get_coordinates(gdf.geometry, include_z=True)

print(c)

Result:

[[0. 0. 2.]
[0. 1. 2.]
[1. 0. 2.]]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.