5

I have geopandas with CRS in meters (ITM {'init' :'epsg:2039'}).

I converted the geometry from espg:4326 so I have very high precision which I don't require: POINT (177559.4776412862 594546.4983892406)

How can I truncate the redundant digits after the floating-point? I tried to use:

df.geometry = df.geometry.simplify(0.5) but I get an error:

can't set attribute

3
  • what if you try df['coord2'] = df['coordinates'].apply(lambda x: np.round(np.array(x),2)?
    – Taras
    Commented Sep 19, 2019 at 13:14
  • I followed your advice, though I would prefer to avoid using apply... df.geometry.apply(lambda p: sg.Point(np.trunc(p.x),np.trunc(p.y)))
    – Shakedk
    Commented Sep 19, 2019 at 14:19
  • 1
    look at Rounding all coordinates in shapely?
    – gene
    Commented Sep 19, 2019 at 15:10

2 Answers 2

7

The simplify method is meant for simplifying lines or polygons: reducing the number of vertices (thus reducing the number of coordinates, not the precision of each coordinate).
So for points, this has no effect (and even for lines and polygons, it does not do what you are after). The actual error you get is from the fact that you cannot overwrite the geometries using df.geometry =, you need to use the actual column name like df['geometry'] = ... to do that.

Then to come to your actual question: limiting the precision (rounding) the coordinates.

First, in most cases this is not actually a problem to have this precision, but rather it might be a display issue: you prefer to not see those many numbers when looking at the data, as those many decimals are irrelevant?
In that case, there is actually work being done in GeoPandas to do exactly that by default: https://github.com/geopandas/geopandas/pull/1057. You can already do this on individual points when converting to WKT:

>>> import shapely.geometry
>>> p = shapely.geometry.Point(177559.4776412862, 594546.4983892406)
>>> print(p)  
POINT (177559.4776412862 594546.4983892406)

>>> import shapely.wkt
>>> shapely.wkt.dumps(p, rounding_precision=2)
'POINT (177559.48 594546.50)'

If you actually want to round the coordinates: there is no direct way to do this with GeoPandas or Shapely. Some workarounds include getting the coordinates, rounding, and recreating the geometries. Or, outputting to WKT with a given precision, and loading it back, as mentioned in this answer: https://gis.stackexchange.com/a/276512/9828
For points this is still relatively easy:

# with p from above
>>> p_rounded = shapely.geometry.Point(*np.round(np.array(p.coords), 2))
>>> print(p_rounded)
POINT (177559.48 594546.5)

But for (multi)linestrings or (multi)polygons this gets much more complicated, so then the WKT way might be best (although less efficient):

>>> p_rounded = shapely.wkt.loads(shapely.wkt.dumps(p, rounding_precision=2)) 
>>> print(p_rounded)
POINT (177559.48 594546.5)

Both of these approaches could be applied on a full GeoSeries with apply.

But again, in most cases you don't care about those floating points for the actual coordinates (also rounded numbers have them, it is still a floating point), and it is mainly a display issue.

3
  • Thanks! But apart from display issue, I can also reduce the size of my df if I'm rounding points and using smaller data types, no?
    – Shakedk
    Commented Sep 22, 2019 at 7:13
  • No, rounding will not change the fact that it are floating point numbers, and those will use the same amount of memory, even when rounded.
    – joris
    Commented Sep 23, 2019 at 6:51
  • But then I can work with float32 instead of float64 and it reduces the space
    – Shakedk
    Commented Sep 23, 2019 at 10:28
1

Since december 2022, shapely.set_precision has been available for this purpose. This function will round the coordinates but will also make sure the output is a valid geometry, as with polygons just rounding coordinates can easily lead to self-intersections,...:

import shapely

# Round the coordinates to 5 decimals
gdf.geometry = shapely.set_precision(gdf.geometry, grid_size=0.00001)

In GeoPandas 1.0, planned to be released 31 march 2024, set_precision will also be available like this:

# Round the coordinates to 5 decimals
gdf.geometry = gdf.geometry.set_precision(grid_size=0.00001)

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.