Search code examples
pythongeopandasmarkerfolium

geopandas .explore - How to set marker icon?


I want to change the icon of the marker in .explore to a house icon.

I have read the documentation of geopandas.GeoDataFrame.explore and folium, still not able to understand it.

geo_df.explore(m=m
                    ,column='pop'
                    ,tooltip={"name","pop"}     
                    ,cmap='summer'
                    ,style_kwds=dict(stroke=True,weight=1,color='black', opacity=0.5, fillOpacity=0.9)
                    ,marker_kwds=dict(radius=5,icon=folium.Icon(icon='house-blank'))              
                    ,name="Residental"
                    )

The icon represents the position of the house and I set colormap base on an integer value.

enter image description here

Also, is there a way to make a radius size don't change when zoom?


Solution

  • There is a feature in folium GeoJson Marker and a feature in geopandas flexible style function that can be used to meet your requirement

    1. make your code a MWE using cities dataset
    2. define marker_type and marker_kwds so that a DivIcon is used
    3. define a style function so that marker is formatted as you require. Actually using column created by geopandas from column and cmap parameters
    4. the size of markers does not change on zoom as font-size has been set in pixels
    import geopandas as gpd
    import folium
    import numpy as np
    
    geo_df = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
    geo_df["pop"] = np.random.randint(1, 5, len(geo_df))
    m = None
    
    m = geo_df.explore(
        m=m,
        column="pop",
        tooltip={"name", "pop"},
        cmap="summer",
        style_kwds=dict(
            style_function=lambda x: {
                "html": f"""<span   class="fa fa-home" 
                                    style="color:{x["properties"]["__folium_color"]};
                                    font-size:14px"></span>"""
            },
        ),
        marker_type="marker",
        marker_kwds=dict(icon=folium.DivIcon()),
        name="Residental",
        height=300,
        width=300,
    )
    
    m
    

    output

    enter image description here

    responsive and icon borders

    using this as inspiration Injecting CSS and JavaScript into folium

    import geopandas as gpd
    import folium
    import numpy as np
    
    geo_df = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
    geo_df["pop"] = np.random.randint(1, 5, len(geo_df))
    m = None
    
    m = geo_df.explore(
        m=m,
        column="pop",
        tooltip={"name", "pop"},
        cmap="summer",
        style_kwds=dict(
            style_function=lambda x: {
                "html": f"""<span   class="fa fa-home" 
                                    style="color:{x["properties"]["__folium_color"]};">
                            </span>"""
            },
        ),
        marker_type="marker",
        marker_kwds=dict(icon=folium.DivIcon(class_name="mapIcon")),
        name="Residental",
        height=300,
        width=500,
    )
    
    # inject html into the map html
    m.get_root().html.add_child(
        folium.Element(
            """
    <style>
    .mapIcon {
        font-size:large;
        text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
    }
    </style>
    <script type="text/javascript">
    window.onload = function(){
        var sizeFromZoom = function(z){return z<3 ? "small" : (0.5*z)+"em"}
        var updateIconSizes = function(){
            var mapZoom = {mapObj}.getZoom();
            var txtSize = sizeFromZoom(mapZoom);
            $(".mapIcon").css("font-size", txtSize);
        }
        updateIconSizes();
        {mapObj}.on("zoomend", updateIconSizes);
    }
    </script>
    """.replace(
                "{mapObj}", m.get_name()
            )
        )
    )
    
    m