I imported a shapefile in the form of a pandas.dataframe and ran operations on it. But I can't convert the dataframe to a geodataframe. I tried with gpd.GeoDataFrame, and with wkt.loads. I think it's because of the format of my geometry: they're Polygon Z:

0 POLYGON Z((653467.7 6840811 81.5 ...))

Here is my code when I try to create a geometry column before the conversion to GeoDataFrame


and the error :

Traceback (most recent call last):
  File "cleanshp.py", line 34, in <module>
  File "/home/windmyroof/.local/lib/python3.7/site-packages/pandas/core/series.py", line 4200, in apply
    mapped = lib.map_infer(values, f, convert=convert_dtype)
  File "pandas/_libs/lib.pyx", line 2388, in pandas._libs.lib.map_infer
  File "/home/windmyroof/.local/lib/python3.7/site-packages/shapely/wkt.py", line 10, in loads
    return geos.WKTReader(geos.lgeos).read(data)
  File "/home/windmyroof/.local/lib/python3.7/site-packages/shapely/geos.py", line 279, in read
    raise TypeError("Only str is accepted.")
TypeError: Only str is accepted.

The code with the shapefile import as a geodataframe (seems good), and an attempt of export shapefile (that fails) :

import geopandas as gpd
import pandas as pd
from shapely.ops import unary_union
from shapely.geometry import Point, Polygon
from shapely import wkt

def import_shapefile(path):
    # import shapefile using geopandas
    sjer_plot_locations = gpd.read_file(path)

    # create right dataset for geometry reconstruction
    columns = ['BAT_ID', 'BAT_COORD', 'BAT_HAUTEUR', 'Z_SOL']
    bat = gpd.GeoDataFrame(index=range(len(sjer_plot_locations.geometry[:])), columns=columns)

    for i in range(len(sjer_plot_locations.geometry[:])):
        bat.at[i, 'BAT_ID'] = sjer_plot_locations.ID[i]
        bat.at[i, 'BAT_HAUTEUR'] = sjer_plot_locations.HAUTEUR[i]
        bat.at[i, 'Z_SOL'] = sjer_plot_locations.Z_MIN_SOL[i]
        bat.at[i, 'BAT_COORD'] = sjer_plot_locations.geometry[i]

    return bat, sjer_plot_locations

bat, sjer = import_shapefile('/home/windmyroof/salome_shp/bats.shp')

n_bats = [i for i in range(len(bat.index))]

# cleaning geometry
# u = unary_union([bat.at[i, 'BAT_COORD'] for i in range(len(bat.index)) if i in n_bats])
# u = u.simplify(0.5)


And the error :

Traceback (most recent call last):
  File "cleanshp.py", line 33, in <module>
  File "/home/windmyroof/.local/lib/python3.7/site-packages/geopandas/geodataframe.py", line 746, in to_file
    _to_file(self, filename, driver, schema, index, **kwargs)
  File "/home/windmyroof/.local/lib/python3.7/site-packages/geopandas/io/file.py", line 239, in _to_file
    schema = infer_schema(df)
  File "/home/windmyroof/.local/lib/python3.7/site-packages/geopandas/io/file.py", line 299, in infer_schema
    geom_types = _geometry_types(df)
  File "/home/windmyroof/.local/lib/python3.7/site-packages/geopandas/io/file.py", line 316, in _geometry_types
    geom_types_2D = df[~df.geometry.has_z].geometry.geom_type.unique()
  File "/home/windmyroof/.local/lib/python3.7/site-packages/pandas/core/generic.py", line 5130, in __getattr__
    return object.__getattribute__(self, name)
  File "/home/windmyroof/.local/lib/python3.7/site-packages/geopandas/geodataframe.py", line 173, in _get_geometry
    " column '%s'.)" % self._geometry_column_name
AttributeError: No geometry data set yet (expected in column 'geometry'.)

I fixed the problem using the comments. It was necessary to rename the column 'BAT_COORD' to 'geometry'. Indeed importing directly in gdp and not pd works very well.

  • 2
    Why arent you reading the shape into a geodataframe? gpd.read_file("path/to/shapefile.shp"). Might be easier than pandas -> geopandas – BERA Aug 3 '20 at 13:38
  • 1
    thanks for your answer, I tried and it works, but I always have the problem : I want to export the shapefile on which I made operation to a new shapefile. I want to use the gpd.to_file function for that. This function requires the argument "geometry" which I can't extract. – benoitWMR Aug 3 '20 at 13:52
  • It seems from the output string that the geometry is already a Shapely geometry object. As the error message says, loads expects a string object. I think you just setting the geometry column should be enough to create a GeoDataFrame, you don't need to convert something. Can you add the code how you tried to create the GeoDataFrame? – mwil.me Aug 4 '20 at 2:26
  • Yes I edited my question in which i added the code – benoitWMR Aug 4 '20 at 14:48
  • Please cut and paste your answer from the area reserved for questions into the area reserved for answers. It is fine and encouraged to self-answer. – PolyGeo Aug 9 '20 at 10:34

Import directly to geopandas is definitely the right move. The only step you are missing is setting which column contains the geometry! Try add this line before writing to file:

bat.set_geometry('BAT_COORD', inplace=True)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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