Search code examples
python-3.xplotlyvisualizationflagsflagpy

Using flags to incorporate a graphic in plotly - Flagpy in plotly not working


I am trying to make a graphic and put a flag next to it in each barchart. For that I am using flagpy and plotly. But it does not seem like it is working. This is as far as I have gotten. Could you help me ? Here you have a dummy code to it, with the countries as well.

import plotly.graph_objects as go
import pandas as pd
import flagpy as fp


# fp.get_flag_img function from flagpy

# Your DataFrame setup
df_date_top_n = pd.DataFrame({
    'CTR_DSC': ['Spain', 'Canada', 'Germany'],
    'PLT_NAM_DSC': ['Plant A', 'Plant B', 'Plant C'],
    'KPI_VAL': [100, 200, 150],
    'flag_emoji': ['🇪🇸', '🇨🇦', '🇩🇪']
})

# Sorting
df_date_top_n.sort_values('KPI_VAL', ascending=True, inplace=True)

# Create the plot
fig = go.Figure()

# Add bars
fig.add_trace(go.Bar(
    x=df_date_top_n['KPI_VAL'],
    y=df_date_top_n['PLT_NAM_DSC'],
    orientation='h',
    text=df_date_top_n['KPI_VAL'],
    textposition='auto',
    opacity=0.8,
))

# If you remove this you get the function
for i, row in df_date_top_n.iterrows():
    # Correctly using CTR_DSC to fetch flag images
    flag_url = fp.get_flag_img(row['CTR_DSC'])  
    fig.add_layout_image(
        dict(
            source=Image.open(flag_url),
            xref="x", yref="y",
            x=row['KPI_VAL'] - 5,  # Adjusting this value for better visibility
            y=row['PLT_NAM_DSC'],
            sizex=0.05, sizey=0.05,  # Adjust size as necessary
            xanchor="center", yanchor="middle",
            sizing="contain",
            opacity=0.8,
            layer="above"
        )
    )

# Customize layout
fig.update_layout(
    title='Top Plant Consumption',
    xaxis_title="MWH",
    yaxis_title="Factory Name",
)

# Show the figure
fig.show()

I want next to 200 the flag of the correspondent country in df_date_top_n['CTR_DSC'] Thank you for your time in advanced,

enter image description here

For more information, the function outputs this:

img = fp.get_flag_img('Germany')
img

enter image description here


Solution

  • This worked out for me source=PIL.Image.open(urllib.request.urlopen(row["flag_url"])), such that:

    import plotly.graph_objects as go
    import pandas as pd
    import matplotlib.pyplot as plt
    
    
        # Assuming fp.get_flag_img function exists and works with country names or codes to return a flag image URL
    
        # Your DataFrame setup
        df_date_top_n = pd.DataFrame({
            'CTR_DSC': ['Spain', 'Canada', 'Germany'],
            'PLT_NAM_DSC': ['Plant A', 'Plant B', 'Plant C'],
            'KPI_VAL': [100, 200, 150],
            'flag_emoji': ['🇪🇸', '🇨🇦', '🇩🇪']
        })
        # Assuming get_country_alpha_2_code is your function that returns a two-letter country code
        df_date_top_n['flag_url'] = df_date_top_n['CTR_DSC'].apply(lambda country_name: f"https://flagcdn.com/h20/{get_country_alpha_2_code(country_name).lower()}.png")
        print(df_date_top_n)
    
        # Sorting
        df_date_top_n.sort_values('KPI_VAL', ascending=True, inplace=True)
    
        # Create the plot
        fig = go.Figure()
    
        # Add bars
        fig.add_trace(go.Bar(
            x=df_date_top_n['KPI_VAL'],
            y=df_date_top_n['PLT_NAM_DSC'],
            orientation='h',
            text=df_date_top_n['KPI_VAL'],
            textposition='auto',
            opacity=0.8,
        ))
    
        # If you remove this you get the function
        for i, row in df_date_top_n.iterrows():
            # Correctly using CTR_DSC to fetch flag images
            
            fig.add_layout_image(
                dict(
                    source=PIL.Image.open(urllib.request.urlopen(row["flag_url"])),
                    xref="x", yref="y",
                    x=row['KPI_VAL'] - 5,  # Adjusting this value for better visibility
                    y=row['PLT_NAM_DSC'],
                    sizex=10, sizey=10,  # Adjust size as necessary
                    xanchor="center", yanchor="middle",
                    sizing="contain",
                    opacity=0.8,
                    layer="above"
                )
            )
    
        # Customize layout
        fig.update_layout(
            title='Top Plant Consumption',
            xaxis_title="MWH",
            yaxis_title="Factory Name",
        )
    
        # Show the figure
        fig.show()
    

    enter image description here. Now it is only adjusting.