2

My professor gave us a basic Python script that demonstrated how Shapely works with a shapefile, however it's not working for me. Here is the code:

from shapely.geometry import mapping, shape
from fiona import collection

with collection("hawaii_vector_data.shp","r") as input:
  for polygon in input:
    c = polygon['properties']['class']
    if c == 0 or c == None:
      continue
    s = shape(polygon['geometry'])
    print s

and when I run it I get this Traceback error:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    c = polygon['properties']['class']
KeyError: 'class'

Since I am new to using Shapely I have no idea what the error might be. Any advice would be great.

  • From your error message I assume that the imports are not the problem, but you should probably edit your post to include them in the code block as well. In your above snippet, without the line break the program would crash when you try to import Fiona. I would edit it for you, but not allowed to add two characters as an edit :-) – BritishSteel Feb 19 '15 at 20:40
  • 1
    Looks like your hawaii_vector_data.shp shapefile doesn't have a class attribute. – Mike T Feb 19 '15 at 20:57
3

Fiona uses dictionaries to read shapefiles

1) the keys of the dictionary = schema of the shapefile

shapes = fiona.open("polygons.shp")
# schema of the shapefile -> the keys of the dictionary
print shapes.schema
{'geometry': 'Polygon', 'properties': OrderedDict([(u'id', 'int:10')])}
# read first feature of the shapefile
first = shapes.next()
print first
{'geometry': {'type': 'Polygon', 'coordinates': [[(151116.87238259654, 135890.8706318218), (153492.19971554304, 134793.3055883224), (153934.50204650551, 133892.31935858406), (152623.97662143156, 131811.86024627919), (150903.91200102202, 130894.49244872745), (149347.66305874675, 132991.33312884573), (149151.08424498566, 134383.76639298678), (151116.87238259654, 135890.8706318218)]]}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'id', 2)])}

2) the geometry key

print first['geometry'] # GeoJSON format
{'type': 'Polygon', 'coordinates': [[(151116.87238259654, 135890.8706318218), (153492.19971554304, 134793.3055883224), (153934.50204650551, 133892.31935858406), (152623.97662143156, 131811.86024627919), (150903.91200102202, 130894.49244872745), (149347.66305874675, 132991.33312884573), (149151.08424498566, 134383.76639298678), (151116.87238259654, 135890.8706318218)]]}
# the coordinates of the geometry
print ['geometry']["coordinates"]
[[(151116.87238259654, 135890.8706318218), (153492.19971554304, 134793.3055883224), (153934.50204650551, 133892.31935858406), (152623.97662143156, 131811.86024627919), (150903.91200102202, 130894.49244872745), (149347.66305874675, 132991.33312884573), (149151.08424498566, 134383.76639298678), (151116.87238259654, 135890.8706318218)]]

If you want to transform the geometry to a Shapely geometry

poly = shape(first['geometry']
print poly
POLYGON ((151116.8723825965 135890.8706318218, 153492.199715543 134793.3055883224, 153934.5020465055 133892.3193585841, 152623.9766214316 131811.8602462792, 150903.912001022 130894.4924487275, 149347.6630587468 132991.3331288457, 149151.0842449857 134383.7663929868, 151116.8723825965 135890.8706318218))

3) the attributes -> property key

print first['property']
OrderedDict([(u'id', 2)])
# value of attribute id
print fist['properties']['id']
2

4) you problem

with fiona.open("polygons.shp") as input:
    for polygon in input:
        c = polygon['properties']['id']
        s = shape(polygon['geometry'])
        print c, s
....

And you can see that the error in your script comes from the fact that there is no "class" key in the properties of your shapefile.

If you want to select some features:

with fiona.open("polygons.shp") as input:
    for polygon in input:
        if polygon['properties']['id'] > 0:
             s = shape(polygon['geometry'])
             print c, s
  • There was in fact no "class" attribute. I used QGIS to convert a raster file to vector. When it prompted me to fill in the output location there was also a text box called "field name" that I could have filled in with "class" but it defaulted to "DN". – steveclark Feb 21 '15 at 3:50

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.