Search code examples
geopandasfolium

How to add hover value in folium map


I'm trying to create a folium map that contains Manhattan location clusters. I have a geojson file that contains clusters geometry of the and pandas data frame which contains the counts value

pandas dataframe

reading the geojson file

geojson

then I joined the two files merged file

then converted the merged file to json to json

now I created the folium map which contains the clusters and reflects the trips count by color.

m = folium.Map(location=[40.7831, -73.9712], zoom_start=11, tiles="cartodbpositron")
choropleth = folium.Choropleth(
    geo_data=geo_json_data,
    data=filter_data_new,
    columns=['LocationID', 'Trips_Forcast'],
    key_on='feature.properties.LocationID',
    fill_color='BuPu', 
    fill_opacity=0.7, 
    line_opacity=0.2,
    legend_name='Avg',
    reset=True,
    highlight=True,
).add_to(m)


m

map

now I'm trying to add hover to show the trip count value on the map using the following code.

m = folium.Map(location=[40.7831, -73.9712], zoom_start=11, tiles="cartodbpositron")
choropleth = folium.Choropleth(
    geo_data=geo_json_data,
    data=filter_data_new,
    columns=['LocationID', 'Trips_Forcast'],
    key_on='feature.properties.LocationID',
    fill_color='BuPu', 
    fill_opacity=0.7, 
    line_opacity=0.2,
    legend_name='Avg',
    reset=True,
    highlight=True,
).add_to(m)

choropleth.geojson.add_child(
    folium.features.GeoJsonTooltip(fields=['LocationID', 'Trips_Forcast'],
                                   aliases=['LocationID:', 'Trips_Forcast:'],
                                   labels=True,
                                   localize=True,
                                   sticky=False,
                                   style="""
                                   background-color: #F0EFEF;
                                   border: 2px solid black;
                                   border-radius: 3px;
                                   box-shadow: 3px;
                                   """,)
)


m

I got this error message and i can't solve it

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\miniconda3\envs\geo_env\lib\site-packages\IPython\core\formatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

~\miniconda3\envs\geo_env\lib\site-packages\folium\folium.py in _repr_html_(self, **kwargs)
    297             self._parent = None
    298         else:
--> 299             out = self._parent._repr_html_(**kwargs)
    300         return out
    301 

~\miniconda3\envs\geo_env\lib\site-packages\branca\element.py in _repr_html_(self, **kwargs)
    324     def _repr_html_(self, **kwargs):
    325         """Displays the Figure in a Jupyter notebook."""
--> 326         html = escape(self.render(**kwargs))
    327         if self.height is None:
    328             iframe = (

~\miniconda3\envs\geo_env\lib\site-packages\branca\element.py in render(self, **kwargs)
    319         """Renders the HTML representation of the element."""
    320         for name, child in self._children.items():
--> 321             child.render(**kwargs)
    322         return self._template.render(this=self, kwargs=kwargs)
    323 

~\miniconda3\envs\geo_env\lib\site-packages\folium\folium.py in render(self, **kwargs)
    366             '</style>'), name='map_style')
    367 
--> 368         super(Map, self).render(**kwargs)
    369 
    370     def fit_bounds(self, bounds, padding_top_left=None,

~\miniconda3\envs\geo_env\lib\site-packages\folium\elements.py in render(self, **kwargs)
     19             figure.header.add_child(CssLink(url), name=name)
     20 
---> 21         super().render(**kwargs)

~\miniconda3\envs\geo_env\lib\site-packages\branca\element.py in render(self, **kwargs)
    626 
    627         for name, element in self._children.items():
--> 628             element.render(**kwargs)

~\miniconda3\envs\geo_env\lib\site-packages\folium\features.py in render(self, **kwargs)
   1305             self.color_scale._parent = self._parent
   1306 
-> 1307         super(Choropleth, self).render(**kwargs)
   1308 
   1309 

~\miniconda3\envs\geo_env\lib\site-packages\branca\element.py in render(self, **kwargs)
    626 
    627         for name, element in self._children.items():
--> 628             element.render(**kwargs)

~\miniconda3\envs\geo_env\lib\site-packages\folium\features.py in render(self, **kwargs)
    624                 self.highlight_map = mapper.get_highlight_map(
    625                     self.highlight_function)
--> 626         super(GeoJson, self).render()
    627 
    628 

~\miniconda3\envs\geo_env\lib\site-packages\branca\element.py in render(self, **kwargs)
    626 
    627         for name, element in self._children.items():
--> 628             element.render(**kwargs)

~\miniconda3\envs\geo_env\lib\site-packages\folium\features.py in render(self, **kwargs)
    914         if isinstance(self._parent, GeoJson):
    915             keys = tuple(self._parent.data['features'][0]['properties'].keys())
--> 916             self.warn_for_geometry_collections()
    917         elif isinstance(self._parent, TopoJson):
    918             obj_name = self._parent.object_path.split('.')[-1]

~\miniconda3\envs\geo_env\lib\site-packages\folium\features.py in warn_for_geometry_collections(self)
    898     def warn_for_geometry_collections(self):
    899         """Checks for GeoJson GeometryCollection features to warn user about incompatibility."""
--> 900         geom_collections = [
    901             feature.get('properties') if feature.get('properties') is not None else key
    902             for key, feature in enumerate(self._parent.data['features'])

~\miniconda3\envs\geo_env\lib\site-packages\folium\features.py in <listcomp>(.0)
    901             feature.get('properties') if feature.get('properties') is not None else key
    902             for key, feature in enumerate(self._parent.data['features'])
--> 903             if feature['geometry']['type'] == 'GeometryCollection'
    904         ]
    905         if any(geom_collections):

TypeError: 'NoneType' object is not subscriptable

<folium.folium.Map at 0x22b0be1cbe0>

all what i want to do is to add hover on the map that show the trips value, something like this enter image description here since days I can't figure it out. can anyone help with that


Solution

  • Since geopandas 0.10 folium generation has been integrated into explore(). Hence solution further simplifies:

    import geopandas as gpd
    import pandas as pd
    import numpy as np
    
    url = "https://raw.githubusercontent.com/codeforgermany/click_that_hood/main/public/data/manhattan.geojson"
    gpd_geo = gpd.read_file(url)
    
    gpd_geo_new = gpd_geo[["cartodb_id", "name", "geometry"]]
    filter_data_new = pd.DataFrame(
        {
            "cartodb_id": gpd_geo_new["cartodb_id"].unique(),
            "Trips_Forcast": np.random.randint(10, 500, len(gpd_geo_new)),
        }
    )
    filter_data_new = gpd_geo_new.merge(filter_data_new, on="cartodb_id", how="left")
    
    filter_data_new.explore("Trips_Forcast", cmap="BuPu")
    

    enter image description here