3

Using ogr2ogr in Python, I am trying to convert a CSV to a shapefile. One column in the CSV, named "Polygon", contains WKT like this: POLYGON((long lat, long lat, long lat, etc.)) Currently, I can make a polygon shapefile with the correct projection, but the geometry is empty.

How can I modify my ogr2ogr arguments to correctly create the geometry using the WKT in each row? Currently I have something like this:

ogr2ogr.main(["", "-a_srs", "EPSG:4326", "-f", "ESRI Shapefile", "output.shp", "input.csv", "-nlt", "POLYGON"])
Mike T
  • 41,085
  • 18
  • 152
  • 203
Daniel W
  • 31
  • 1
  • 2
  • Welcome to SO and nice first post. Hopefully somebody will be able to help you on SO. If you don't get any responses after a day or two, you might also check out the [GIS SE](http://gis.stackexchange.com/) site. Your post is about coding, so its appropriate for here as well. – Richard Erickson Aug 10 '15 at 19:50
  • 1
    Don't [cross-post](http://gis.stackexchange.com/q/157745/1872) – Mike T Aug 10 '15 at 20:33

1 Answers1

2

I'm not really used to ogr2ogr.py but if you know some basics with python bindings for ogr it can be done quite easily. Here is a simple example which do what you are trying to do.

import ogr, osr, csv

spatialref = osr.SpatialReference()  # Set the spatial ref.
spatialref.SetWellKnownGeogCS('WGS84')  # WGS84 aka ESPG:4326
driver = ogr.GetDriverByName("ESRI Shapefile") # Shapefile driver
dstfile = driver.CreateDataSource('output.shp') # Your output file

# Please note that it will fail if a file with the same name already exists
dstlayer = dstfile.CreateLayer("layer", spatialref, geom_type=ogr.wkbPolygon) 

# Add the other attribute fields needed with the following schema :
fielddef = ogr.FieldDefn("ID", ogr.OFTInteger)
fielddef.SetWidth(10)
dstlayer.CreateField(fielddef)

fielddef = ogr.FieldDefn("Name", ogr.OFTString)
fielddef.SetWidth(80)
dstlayer.CreateField(fielddef)

# Read the features in your csv file:
with open('/path/to/file.csv') as file_input:
    reader = csv.reader(file_input)  # Can be more intuitive with a DictReader (adapt to your needs)
    next(reader) # Skip the header
    for nb, row in enumerate(reader): 
        # WKT is in the second field in my test file :
        poly = ogr.CreateGeometryFromWkt(row[1])
        feature = ogr.Feature(dstlayer.GetLayerDefn())
        feature.SetGeometry(poly)
        feature.SetField("ID", nb) # A field with an unique id.
        feature.SetField("Name", row[0]) # The name (expected to be in the first column here)
        dstlayer.CreateFeature(feature)
    feature.Destroy()
    dstfile.Destroy()

This code assumes that your CSV has two columns, the first one with a name to use and the second one containing the geometry in WKT as asked, so for example something in the following form:

"Name","Polygons"
"Name1","POLYGON((1 1,5 1,5 5,1 5,1 1))"
"Name2","POLYGON((6 3,9 2,9 4,6 3))"

Of course it need to be adapted on your specific case, but this snippet of code can be a first start and will do the job.
(And if you want some other examples on GDAL/ogr python bindings you can have a look on these recipes)

mgc
  • 5,223
  • 1
  • 24
  • 37
  • 1
    Thanks for both answers mgc. As someone that is new to Python and programming in general, it's really appreciated. I'll try to modify my code with [this](http://gis.stackexchange.com/a/157965/56509) first, and if that fails I'll come back to this answer. – Daniel W Aug 12 '15 at 14:26
  • Can you please explain the "with open('input.shp') as file_input" part? I'm trying to use the scrupt but it gets error : FileNotFoundError: [Errno 2] No such file or directory: 'input.shp' and I thought this is new name – Reut Aug 30 '20 at 08:40
  • 1
    @Reut this is definitely a mistake in my code. You have to replace "input.shp" with the path of your **csv** file. I will edit my answer. – mgc Aug 30 '20 at 10:13
  • 1
    @Reut i edited my post, dont hesitate if its still unclear. – mgc Aug 30 '20 at 10:20