Search code examples
pythonplotlygeopandassubplotfolium

use Folium map in plotly subplots to create dashboard


I have a plan area that covers several buildings. I want to map the plan and the building in a subplot using gdf.explore() method that creates a folium map object, and then use plotly to map a graph of building years histogram. Then put these two plots side by side.

I could not find a way to add folium map object in plotly subplots.

Here is what I need in code:

m = gdf.explore()
p = px.histogram()


# CODE THAT PUTS m AND p IN ONE GRAPH!

Thank you in advance!


Solution

    • your question does not contain sample geometry or dataframe. Have synthesized some
    • as per comments plotly and folium are very different libraries with no integration
    • clearly with HTML you can integrate using IFrame. Have taken approach of using data URI to encode plotly and folium components into a single HTML document
    import shapely.geometry
    import numpy as np
    import geopandas as gpd
    import pandas as pd
    import plotly.express as px
    from IPython.display import IFrame
    from datauri import DataURI
    from pathlib import Path
    
    # create a folium map
    m = gpd.GeoDataFrame(
        geometry=[
            shapely.geometry.MultiPoint(
                np.random.uniform(b, b + 1, size=(5, 2))
            ).convex_hull
            for b in range(4)
        ],
        data={"building": [f"building {b}" for b in range(4)]},
    ).explore(column="building")
    
    # create a histogram
    fig = px.histogram(
        pd.DataFrame(
            np.random.randint(1980, 2022, size=(100, 4)),
            columns=[f"b {b}" for b in range(4)],
        )
        .stack()
        .reset_index()
        .rename(columns={0: "year", "level_1": "b"}),
        x="year",
        color="b",
    ).update_layout(margin={"l": 0, "r": 0, "t": 0, "b": 0})
    
    html = f"""<html>
    <body>
        <div style="display:inline-block;width:1200">
            <iframe src='{DataURI.make("text/html", charset="us-ascii", base64=True, data=m._parent.render())}' 
                width="49%", align="left"></iframe>
            <iframe src='{DataURI.make("text/html", charset="us-ascii", base64=True, data=fig.to_html(include_plotlyjs="cdn"))}'
                width="49%", align="right"></iframe>
        </div>
    </body>
    </html>"""
    
    # as a HTML file
    with open(Path.cwd().joinpath("sample.html"), "w") as f:
        f.write(html)
    
    # as jupyter output
    IFrame(
        DataURI.make("text/html", charset="utf-8", base64=True, data=html),
        height=900,
        width=1200,
    )
    

    enter image description here