GeoJSON Format is like below :
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":
{
"type":"Polygon",
"coordinates":[[[-1.6704591323124895,49.62681486270549], .....
{
"insee":"50173",
"nom":"脡queurdreville-Hainneville",
"wikipedia":"fr:脡queurdreville-Hainneville",
"surf_m2":12940306}},
Pandas DataFrame :
postal_count.head(5)
Out[95]:
Code_commune_INSEE count
0 75120 723
1 75115 698
2 75112 671
3 75118 627
4 75111 622
Here is my code (snippet from this notebook)
map_france = folium.Map(location=[47.000000, 2.000000], zoom_start=6)
map_france.choropleth(
geo_str=open(path + 'simplified_communes100m.json').read(),
data=postal_count,
columns=['Code_commune_INSEE', 'count'],
key_on='feature.geometry.properties.insee',
fill_color='YlGn',
)
map_france.save(table_path+ '/choro_test1.html')
I'm stilling getting this error again and again :
AttributeError Traceback (most recent call last)
<ipython-input-83-ea0fd2c1c207> in <module>()
8 fill_color='YlGn',
9 )
---> 10 map_france.save('/media/flo/Stockage/Data/MesAides/map/choro_test1.html')
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/element.py in save(self, outfile, close_file, **kwargs)
151
152 root = self.get_root()
--> 153 html = root.render(**kwargs)
154 fid.write(html.encode('utf8'))
155 if close_file:
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/element.py in render(self, **kwargs)
357 """Renders the HTML representation of the element."""
358 for name, child in self._children.items():
--> 359 child.render(**kwargs)
360 return self._template.render(this=self, kwargs=kwargs)
361
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/element.py in render(self, **kwargs)
665
666 for name, element in self._children.items():
--> 667 element.render(**kwargs)
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/element.py in render(self, **kwargs)
661 script = self._template.module.__dict__.get('script', None)
662 if script is not None:
--> 663 figure.script.add_children(Element(script(self, kwargs)),
664 name=self.get_name())
665
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/jinja2/runtime.py in __call__(self, *args, **kwargs)
434 raise TypeError('macro %r takes not more than %d argument(s)' %
435 (self.name, len(self.arguments)))
--> 436 return self._func(*arguments)
437
438 def __repr__(self):
<template> in macro(l_this, l_kwargs)
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/jinja2/runtime.py in call(_Context__self, _Context__obj, *args, **kwargs)
194 args = (__self.environment,) + args
195 try:
--> 196 return __obj(*args, **kwargs)
197 except StopIteration:
198 return __self.environment.undefined('value was undefined because '
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/features.py in style_data(self)
352
353 for feature in self.data['features']:
--> 354 feature.setdefault('properties', {}).setdefault('style', {}).update(self.style_function(feature)) # noqa
355 return json.dumps(self.data, sort_keys=True)
356
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in style_function(x)
671 "color": line_color,
672 "fillOpacity": fill_opacity,
--> 673 "fillColor": color_scale_fun(x)
674 }
675
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in color_scale_fun(x)
659 def color_scale_fun(x):
660 return color_range[len(
--> 661 [u for u in color_domain if
662 u <= color_data[get_by_key(x, key_on)]])]
663 else:
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in <listcomp>(.0)
660 return color_range[len(
661 [u for u in color_domain if
--> 662 u <= color_data[get_by_key(x, key_on)]])]
663 else:
664 def color_scale_fun(x):
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in get_by_key(obj, key)
655 return (obj.get(key, None) if len(key.split('.')) <= 1 else
656 get_by_key(obj.get(key.split('.')[0], None),
--> 657 '.'.join(key.split('.')[1:])))
658
659 def color_scale_fun(x):
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in get_by_key(obj, key)
655 return (obj.get(key, None) if len(key.split('.')) <= 1 else
656 get_by_key(obj.get(key.split('.')[0], None),
--> 657 '.'.join(key.split('.')[1:])))
658
659 def color_scale_fun(x):
/home/flo/.virtualenvs/mesaides/lib/python3.4/site-packages/folium/folium.py in get_by_key(obj, key)
653
654 def get_by_key(obj, key):
--> 655 return (obj.get(key, None) if len(key.split('.')) <= 1 else
656 get_by_key(obj.get(key.split('.')[0], None),
657 '.'.join(key.split('.')[1:])))
AttributeError: 'NoneType' object has no attribute 'get'
I tried playing with key_on='feature.geometry.properties.insee' without any success.
There were 2 problems :
1 - The correct access to 'insee' parameters is : key_on='feature.properties.insee'
2- My DataFrame did not contain all the available 'insee' keys, so it was raising a KeyError
After these 2 problems solved, it worked like a charm!
Safe to close then :wink:
Hi,
sorry to open again this issue, but I have a similar error and can't figure out how to point to the right key_on attribute.
My geojson:
{
"type":"Topology",
"arcs":[...],
"transform":{...},
"objects":
"Com01012018_g_WGS84":{
"type":"GeometryCollection",
"geometries": [
{
"arcs":[...],
"type":"Polygon",
"properties": {
"COMUNE": "Borgo Vercelli",
"PRO_COM": 2017,
...
}
},
{...},
]
}
}
My pandas df:
id comune a11y-score
0 Aquila d'Arroscia 65.17
1 Castel del Rio 68.75
2 Castellaneta 71.95
3 Castelvetrano 77.27
4 Montescudo-Monte Colombo 59.65
I want to set the key on "COMUNE" and I am able to loop through geojson very easily:
with open('italy-comuni.json', encoding='utf-8') as json_file:
data = json.load(json_file)
obj = data['objects']
for righe in obj["Com01012018_g_WGS84"]['geometries']:
print(righe['properties']['COMUNE']) #print the name of the City
As suggested by @FloSugar I checked if both this json and my imported dataframe has the same "comune" value (to avoid raising KeyError ) and alla the values in a11y-score are filled (float values from 0 to 100).
Here my Leaflet code:
m = folium.Map(location=[42.833333, 12.833333],zoom_start=6,tiles="Mapbox Bright")
m.choropleth(
geo_data=state_geo,
name='choropleth',
data=italia_df,
columns=['comune', 'a11y-score'],
key_on='object.geometry.properties.COMUNE',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='A11y Score'
)
folium.LayerControl().add_to(m)
Can't figure out how to set key_on properly.
Tried these but nothing actually works:
object.geometries.properties.COMUNE
objects.geometries.properties.comune
objects.Com01012018_g_WGS84.geometry.Polygon.properties.COMUNE
objects.Com01012018_g_WGS84.geometries.Polygon.properties.COMUNE
objects.geometry.Polygon.properties.COMUNE
objects.geometries.Polygon.properties.COMUNE
object.geometries.Polygon.properties.COMUNE
Com01012018_g_WGS84.geometry.properties.COMUNE
Errors:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-19-578cc4d527b5> in <module>()
1 # Save to html
----> 2 m.save('italy-a11yscore.html')
~\Anaconda3\envs\py36\lib\site-packages\branca\element.py in save(self, outfile, close_file, **kwargs)
159
160 root = self.get_root()
--> 161 html = root.render(**kwargs)
162 fid.write(html.encode('utf8'))
163 if close_file:
~\Anaconda3\envs\py36\lib\site-packages\branca\element.py in render(self, **kwargs)
307 """Renders the HTML representation of the element."""
308 for name, child in self._children.items():
--> 309 child.render(**kwargs)
310 return self._template.render(this=self, kwargs=kwargs)
311
~\Anaconda3\envs\py36\lib\site-packages\folium\map.py in render(self, **kwargs)
336 '</style>'), name='map_style')
337
--> 338 super(LegacyMap, self).render(**kwargs)
339
340
~\Anaconda3\envs\py36\lib\site-packages\branca\element.py in render(self, **kwargs)
622
623 for name, element in self._children.items():
--> 624 element.render(**kwargs)
~\Anaconda3\envs\py36\lib\site-packages\branca\element.py in render(self, **kwargs)
618 script = self._template.module.__dict__.get('script', None)
619 if script is not None:
--> 620 figure.script.add_child(Element(script(self, kwargs)),
621 name=self.get_name())
622
~\Anaconda3\envs\py36\lib\site-packages\jinja2\runtime.py in __call__(self, *args, **kwargs)
573 (self.name, len(self.arguments)))
574
--> 575 return self._invoke(arguments, autoescape)
576
577 def _invoke(self, arguments, autoescape):
~\Anaconda3\envs\py36\lib\site-packages\jinja2\asyncsupport.py in _invoke(self, arguments, autoescape)
108 def _invoke(self, arguments, autoescape):
109 if not self._environment.is_async:
--> 110 return original_invoke(self, arguments, autoescape)
111 return async_invoke(self, arguments, autoescape)
112 return update_wrapper(_invoke, original_invoke)
~\Anaconda3\envs\py36\lib\site-packages\jinja2\runtime.py in _invoke(self, arguments, autoescape)
577 def _invoke(self, arguments, autoescape):
578 """This method is being swapped out by the async implementation."""
--> 579 rv = self._func(*arguments)
580 if autoescape:
581 rv = Markup(rv)
<template> in macro(l_1_this, l_1_kwargs)
~\Anaconda3\envs\py36\lib\site-packages\jinja2\runtime.py in call(_Context__self, _Context__obj, *args, **kwargs)
260 args = (__self.environment,) + args
261 try:
--> 262 return __obj(*args, **kwargs)
263 except StopIteration:
264 return __self.environment.undefined('value was undefined because '
~\Anaconda3\envs\py36\lib\site-packages\folium\features.py in style_data(self)
563
564 for feature in self.data['features']:
--> 565 feature.setdefault('properties', {}).setdefault('style', {}).update(self.style_function(feature)) # noqa
566 feature.setdefault('properties', {}).setdefault('highlight', {}).update(self.highlight_function(feature)) # noqa
567 return json.dumps(self.data, sort_keys=True)
~\Anaconda3\envs\py36\lib\site-packages\folium\folium.py in style_function(x)
303 'color': line_color,
304 'fillOpacity': fill_opacity,
--> 305 'fillColor': color_scale_fun(x)
306 }
307
~\Anaconda3\envs\py36\lib\site-packages\folium\folium.py in color_scale_fun(x)
290 def color_scale_fun(x):
291 return color_range[len(
--> 292 [u for u in color_domain if
293 get_by_key(x, key_on) in color_data and
294 u <= color_data[get_by_key(x, key_on)]])]
~\Anaconda3\envs\py36\lib\site-packages\folium\folium.py in <listcomp>(.0)
291 return color_range[len(
292 [u for u in color_domain if
--> 293 get_by_key(x, key_on) in color_data and
294 u <= color_data[get_by_key(x, key_on)]])]
295 else:
~\Anaconda3\envs\py36\lib\site-packages\folium\folium.py in get_by_key(obj, key)
286 return (obj.get(key, None) if len(key.split('.')) <= 1 else
287 get_by_key(obj.get(key.split('.')[0], None),
--> 288 '.'.join(key.split('.')[1:])))
289
290 def color_scale_fun(x):
~\Anaconda3\envs\py36\lib\site-packages\folium\folium.py in get_by_key(obj, key)
285 def get_by_key(obj, key):
286 return (obj.get(key, None) if len(key.split('.')) <= 1 else
--> 287 get_by_key(obj.get(key.split('.')[0], None),
288 '.'.join(key.split('.')[1:])))
289
AttributeError: 'NoneType' object has no attribute 'get'
Thank you for help!
Hi @nittolese, it seems you got the key_on value not right. From the docstring:
Variable in thegeo_dataGeoJSON file to bind the data to. Must start with 'feature' and be in JavaScript objection notation. Ex: 'feature.id' or 'feature.properties.statename'.
Can you try using key_on = 'feature.properties.COMUNE'?
Hi @Conengmo, if I try with
m.choropleth(
geo_data=state_geo,
name='choropleth',
data=italia_df,
columns=['comune', 'a11y-score'],
key_on='feature.properties.comune',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='A11y Score'
)
folium.LayerControl().add_to(m)
m.save('italy-a11yscore.html')
UPDATE: I have edited my GeoJSON, now it looks like this:
{
"type":"FeatureCollection",
"features":[
"type":"Feature",
"geometry": {...},
"properties": {
"comune": "Borgo Vercelli",
"PRO_COM": 2017,
...
I get no error but the html page doesn't show anything of GeoJSON.
I am traversing the GeoJSON with feature.properties.comune . I have no idea why this happens.
You can find gist here
Thanks for your help, so much appreciated
@nittolese the same thing is happening to me. I get no error when I try to key on a lat/lon feature, but nothing shows up on the map.
Maybe you can check for the coordinate reference system (CRS). They should be EPSG:4326.
Most helpful comment
There were 2 problems :
1 - The correct access to 'insee' parameters is :
key_on='feature.properties.insee'2- My DataFrame did not contain all the available 'insee' keys, so it was raising a
KeyErrorAfter these 2 problems solved, it worked like a charm!