[GIS] Adding column to shapefile with Fiona

fionapythonshapefile

I wrote the script to copy a existing shapefile tc_line to a new file tc_pi, and it ran fine:

from shapely.geometry import mapping, shape
import fiona

with fiona.open('tc_line.shp', 'r') as input:
    schema = input.schema.copy()
    input_crs = input.crs
    with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
        for elem in input:
            output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})

Now I want to copy the existing file and add a new column (type: float) containing "1" to the attribute table (I would like the new-added column to be attached to the right of the existing columns in the attribute talle), so I edited the code above to this:

from shapely.geometry import mapping, shape
import fiona

with fiona.open('tc_line.shp', 'r') as input:
    schema = input.schema.copy()
    input_crs = input.crs
    schema['properties']['pi'] = 'float'
    with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
        for elem in input:
            output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})

but error occurred:

Traceback (most recent call last):


File "C:\Users\Heinz\Desktop\test.py", line 10, in <module>
    output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})
  File "C:\Python27\lib\site-packages\fiona\collection.py", line 333, in write
    self.writerecords([record])
  File "C:\Python27\lib\site-packages\fiona\collection.py", line 327, in writerecords
    self.session.writerecs(records, self)
  File "fiona/ogrext.pyx", line 1024, in fiona.ogrext.WritingSession.writerecs (fiona/ogrext.c:17361)
ValueError: Record does not match collection schema: [u'cat_', u'value', u'label'] != ['pi', u'label', u'value', u'cat_']

How to solve this and achieve my objective of 'copy the existing file and add a new column (type: float) containing "1" to the attribute table of new file'?

I am working with python 2.7.12, Fiona 1.7.0

Best Answer

It seems to me that you have some problems with Fiona. Remember that all the elements are dictionaries

1) you define a new field schema['properties']['pi'] = 'float'
2) this field must be in in the properties of every elements

with fiona.open('tc_line.shp', 'r') as input:
    schema = input.schema.copy()
    input_crs = input.crs
    schema['properties']['pi'] = 'float'
    with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
         for elem in input:
              elem['properties']['pi']= 1
              output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})

If you're not comfortable with Python dictionaries, use GeoPandas (it uses Fiona)

import geopandas as gpd
gdf = gpd.read_file("tc_line.shp")
gdf["pi"]= 1
gdf.to_file("tc_pi.shp") 
Related Question