0

I'm working on a function to perform operations on folders of vector files.

These files might have differing attribute fields but there will be a common field between them. I'm using fiona in python to do the work.

A section of code is attached below and I'm using meta = input.meta to gather all the information about the input file to write to the output file.

This is being designed to work on different vector files. So the common field may be different in each run. For example, it might be a string field in one instance or an integer in another.

Despite not knowing beforehand what type of field the input field would be, is it possible to only include the specified field in the output file?

Whilst keeping the other information, such as projection and geometry type, the same as the input.

for file in veclist:
 with fiona.open(file) as input:
 meta = input.meta
 outfilename = os.path.join(outdir, os.path.basename(file).replace('.shp', "_d.shp"))
 with fiona.open(outfilename, 'w', **meta) as output:

I've tried to edit the dictionary of the schema and I've had some success

for file in veclist:
 with fiona.open(file) as input:
 fieldvalue = input.schema['properties'][target_field]
 input.schema['properties'].clear()
 input.schema['properties'][target_field] = fieldvalue
 meta = input.meta
 outfilename = os.path.join(outdir, os.path.basename(file).replace('.shp', "_d.shp"))
 with fiona.open(outfilename, 'w', **meta) as output:

As print(input.schema) listed this:

{'geometry': 'Polygon', 'properties': OrderedDict([('Field_Name', 'str:254')])}

And print(input.meta) listed this:

{'crs': {u'lon_0': -2, u'k': 0.9996012717, u'datum': u'OSGB36', u'y_0': -100000, u'no_defs': True, u'proj': u'tmerc', u'x_0': 400000, u'units': u'm', u'lat_0': 49}, 'driver': u'ESRI Shapefile', 'crs_wkt': u'PROJCS["OSGB_1936_British_National_Grid",GEOGCS["GCS_OSGB 1936",DATUM["OSGB_1936",SPHEROID["Airy_1830",6377563.396,299.3249646]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",49],PARAMETER["central_meridian",-2],PARAMETER["scale_factor",0.9996012717],PARAMETER["false_easting",400000],PARAMETER["false_northing",-100000],UNIT["Meter",1]]', 'schema': {'geometry': 'Polygon', 'properties': OrderedDict([('Field_Name', 'str:254')])}}

But I get this error on trying to write the shapefile:

 File "/.local/lib/python2.7/site-packages/fiona/collection.py", line 355, in write
 self.writerecords([record])
 File "/.local/lib/python2.7/site-packages/fiona/collection.py", line 349, in writerecords
 self.session.writerecs(records, self)
 File "fiona/ogrext.pyx", line 1168, in fiona.ogrext.WritingSession.writerecs
ValueError: Record does not match collection schema: [u'Field_Name', u'pH', u'P_PPM', u'P_Index', u'K_PPM', u'K_Index', u'Mg_PPM', u'Mg_Index', u'2018_y_t_h', u'Grid_ID'] != ['Field_Name']

I thought I had successfully changed my schema and meta when I printed out the results. But it still seems to have picked up the original.

Ok I have gotten slightly further. The issue seem to be due to the next step.

I'm using the dissolve solution from Dissolving polygons based on attributes with Python (shapely, fiona)?

for file in veclist:
 with fiona.open(file) as input:
 fieldvalue = input.schema['properties'][target_field]
 input.schema['properties'].clear()
 input.schema['properties'][target_field] = fieldvalue
 meta = input.meta
 outfilename = os.path.join(outdir, os.path.basename(file).replace('.shp', "_d.shp"))
 with fiona.open(outfilename, 'w', **meta) as output:
 e = sorted(input, key=lambda k: k['properties'][target_field])
 for key, group in itertools.groupby(e, key=lambda x:x['properties'][target_field]):
 properties, geom = zip(*[(feature['properties'], shape(feature['geometry'])) for feature in group])
 print("printing properties")
 print(properties)
 store.append({'geometry': mapping(unary_union(geom)), 'properties': properties[0]})
 print(store)

It's storing all the values of the original fields and attempting to write them to a schema where now only one of the fields exists.

printing properties
(OrderedDict([(u'Grower_ID', 1), (u'Field_Name', u'Black Shed'), (u'pH', 6.0), (u'P_PPM', None), (u'P_Index', u'L+'), (u'K_PPM', None), (u'K_Index', u'M-'), (u'Mg_PPM', None), (u'Mg_Index', u'M'), (u'2018_y_t_h', 7.7), (u'Grid_ID', 291)])

Is it possible to only keep the target_field at this step?

PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Mar 28, 2019 at 14:55
2
  • With Fiona, the meta of a shapefile is a a simple dictionary with geometry and properties as keys that you can modify.( Change Attirbute Name (Fiona) or Fiona - Preffered method for defining a schema for example) Commented Mar 28, 2019 at 16:44
  • can you install geopandas? it'd be geopandas.read_file(filename).loc[:, ['desired_col', 'geometry']].to_file(filename) Commented Apr 3, 2019 at 14:03

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.