GeoPandas – Resolving Saving GeoDataFrame Without Coordinate System

anacondafionageopandaspandaspython

I have

  • GeoPandas 0.2.1 py27_0
  • fiona 1.7.0 np110py27_1
  • Python 2.7.10

installed in Anaconda 2-4.1.1-Windows-x86 environment. I am able to construct GeoDataFrame by reading input datasets and operate the data yet saving an output dataset does not preserve the coordinate system.

import geopandas as gpd
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world.to_file(driver='ESRI Shapefile',filename=r'C:\GIS\Temp\world_out.shp')

The world_out.shp does contain the features and the schema of the source shapefile, but coordinate system is undefined (<Unknown>). The world_out.prj file is 0 KB and doesn't contain anything.

out = gpd.read_file(r'C:\GIS\Temp\world_out.shp')
print out.crs
>>> {}

I have tested to perform this operation using pure Fiona and it works fine, preserving the crs information:

import fiona

datasrc_path = r'C:\Program Files (x86)\ArcGIS\Desktop10.4\TemplateData\TemplateData.gdb'

with fiona.drivers():
    with fiona.open(datasrc_path,layer='cities') as source:
        meta = source.meta
        meta['driver'] = 'ESRI Shapefile'
        meta['layer'] = source.name

        with fiona.open(r'C:\GIS\CitiesFiona.shp', 'w', **meta) as sink:
            for f in source:
                sink.write(f)

The CitiesFiona.prj file does contain the information about the coordinate system.

So, it seems as GeoPandas is not able to read/write crs of the data frame into the output dataset when calling the to_file() method. I have tried calling to_file() on GeoDataFrames constructed from various sources and datasets and the coordinate system information was never present in the output dataset.

Has anyone run into this issue before? Can anyone test this?

Best Answer

I have come across this behavior before.

You need to explicitly pass the well known text (crs_wkt) string to the to_file() method. The string will then get passed to fiona.open(), which writes out the .prj file.

Using your sample code, doing something like this:

ws = r"D:\temp_se"
prj_file = gpd.datasets.get_path('naturalearth_lowres').replace(".shp",".prj")
prj = [l.strip() for l in open(prj_file,'r')][0]
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
temp_shp = os.path.join(ws,"world_out.shp")
world.to_file(filename=temp_shp,driver='ESRI Shapefile',crs_wkt=prj)

should produce: enter image description here

The read_file() and to_file() functions simply serve as wrapper functions. They call fiona.open(), whose signature is shown below:

enter image description here

You need to explicitly pass a crs_wkt value when reading/writing files with geopandas.