Skip to main content
 首页 » 编程设计

pandas之Folium Choropleth + GeoJSON 引发 AttributeError : 'NoneType'

2024年09月07日41Renyi-Fan

我正在尝试使用 folium 做一个 choropleth它在 GeoJSON、Pandas 和传单之间提供了很好的链接。

GeoJSON 格式如下:

{ 
  "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 数据帧:
postal_count.head(5) 
Out[98]:  
  Code_commune_INSEE  CP_count 
0              75120       723 
1              75115       698 
2              75112       671 
3              75118       627 
4              75111       622 

“Code_communes_INSEE”对应于 GeoJSON 中的属性“insee”。我想使用上述 DataFrame 中的变量“CP_count”来做一个 choropleth。

这是我的代码(来自 this notebook 的片段)
map_france = folium.Map(location=[47.000000, 2.000000], zoom_start=6) 
map_france.choropleth( 
                    geo_str=open(geo_path + 'simplified_communes100m.json').read(), 
                    data=postal_count, 
                    columns=['Code_commune_INSEE', 'CP_count'], 
                    key_on='feature.geometry.properties.insee', 
                    fill_color='YlGn', 
) 
map_france.save(table_path + 'choro_test1.html') 

我仍然一次又一次地收到此错误:
--------------------------------------------------------------------------- 
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' 

我试着玩 key_on='feature.geometry.properties.insee'没有任何成功。

请您参考如下方法:

有两个问题:

1 - 对“insee”参数的正确访问是:key_on='feature.properties.insee'
找到合适的最好方法 key_on是使用 geoJSON dict 来确保调用正确的属性。

2- 一旦你有权利 key_on参数,你需要确保 geoJSON 中所有可用的键 包含在您的 Pandas DataFrame 中(否则它会引发 KeyError )

在这种情况下,我使用以下命令行来获取所有 insee我的 geoJSON 包含的键:

ogrinfo -ro -al communes-20150101-100m.shp -geom=NO | grep insee > list_code_insee.txt 

如果您遇到同样的问题,这应该可以解决您的问题。