I'm running through a UTM grid in geojson format with fiona, attempting to add/populate a field based on other field values and then write out to a new file. It appears to successfully build the record but not write it out. An input record looks like this:
{
"type" : "Feature",
"id" : 1201,
"geometry" :
{
"type" : "Polygon",
"coordinates" :
[
[
[-47.9999998938292, -63.9999999562278],
[-47.9999998938292, -64.9999998998828],...
]
]
},
"properties" : {
"FID" : 1201,
"ZONE" : 22,
"ROW_" : "D",
"WEST_VALUE" : " 54W",
"CM_VALUE" : " 51W",
"EAST_VALUE" : " 48W"
}
}
Here is my code:
from collections import OrderedDict
import fiona
gj_file = "/home/me/Downloads/utmzones.geojson"
recs = [] # list of new records that will be written
with fiona.open(gj_file) as source:
source_driver = source.driver
source_crs = source.crs
for f in source:
props = f['properties']
geom = f['geometry']
if props['ROW_'] in ['N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X']:
r = {
'type': 'Feature',
'id': f['id'],
'geometry': geom,
'properties': OrderedDict([
('FID', props['FID']),
('ZONE', props['ZONE']),
('ROW_', props['ROW_']),
('UTMZONE', str(props['ZONE']) + 'N'), # make a ZONE[N/S] value
('WEST_VALUE', props['WEST_VALUE']),
('CM_VALUE', props['CM_VALUE']),
('EAST_VALUE', props['EAST_VALUE'])
])
}
print(r)
recs.append(r)
elif props['ROW_'] in ['M', 'L', 'K', 'J', 'H', 'G', 'F', 'E', 'D', 'C']:
r = {
'type': 'Feature',
'id': f['id'],
'geometry': geom,
'properties': OrderedDict([
('FID', props['FID']),
('ZONE', props['ZONE']),
('ROW_', props['ROW_']),
('UTMZONE', str(props['ZONE']) + 'N'),
('WEST_VALUE', props['WEST_VALUE']),
('CM_VALUE', props['CM_VALUE']),
('EAST_VALUE', props['EAST_VALUE'])
])
}
recs.append(r)
The record generated looks like this:
{
'type': 'Feature',
'id': '1201',
'geometry': {
'type': 'Polygon',
'coordinates': [
[
(-47.9999998938292, -63.9999999562278),
(-47.9999998938292, -64.9999998998828),...
]
]
},
'properties': OrderedDict([
('FID', 1201),
('ZONE', 22),
('ROW_', 'D'),
('UTMZONE', '22N'),
('WEST_VALUE', ' 54W'),
('CM_VALUE', ' 51W'),
('EAST_VALUE', ' 48W')
])
}
My schema looks like this:
schema = {
'geometry': 'Polygon',
'properties': OrderedDict([
('FID', int),
('ZONE', int),
('ROW_', str),
('UTMZONE', str),
('WEST_VALUE', str),
('CM_VALUE', str),
('EAST_VALUE', str)
])
}
And the write action looks like this, based on my (probably incorrect) interpretation of the fiona
docs:
with fiona.open(
'/home/me/Downloads/utm_out.geojson',
'w',
driver=source_driver,
crs=source_crs,
schema=schema) as c:
for rec in recs:
c.write(rec)
This raises an AttributeError: type object 'int' has no attribute 'split'
. When I coerce the two values FID
and ZONE
to str
and update the schema, it then raises a TypeError: argument of type 'type' is not iterable
.
UPDATE: entire stack trace as requested
Traceback (most recent call last):
File "/home/me/PycharmProjects/UTM/join_utm_zones.py", line 63, in <module>
with fiona.open(
File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/env.py", line 417, in wrapper
return f(*args, **kwargs)
File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/__init__.py", line 272, in open
c = Collection(path, mode, crs=crs, driver=driver, schema=this_schema,
File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/collection.py", line 151, in __init__
self._check_schema_driver_support()
File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/collection.py", line 424, in _check_schema_driver_support
field_type = field.split(":")[0]
AttributeError: type object 'int' has no attribute 'split'
Best Answer
Your schema is defined incorrectly. The types need to be defined using strings. You are trying to pass the actual Python object types to the functions, which is causing issues.
Your first error is caused because the library's write utility is trying to call the
.split()
function on the objectint
; it can't becauseint
does have have.split()
method. The second error is different because astr
object does have.split()
method, but then it trips when, presumably, the write utility tries to iterate over a Python type object; a Python type has the type of 'type', hence the weird error.Instead try defining your schema as:
See this section of the documents.