How to display a clickable link pandas dataframe

Hello,

I have a pandas dataframe containing clickable links. In jupyter notebook, it displays a dataframe with clickable links that directs me corresponding directories as shown below:

image

However, when I try to run display the dataframe in streamlit, it wouldn’t render html and does not show the clickable link as shown below:

Here’s a reproducible code for your reference:

import streamlit as st
import pandas as pd

data = [dict(name='Google', url='http://www.google.com'),
        dict(name='Stackoverflow', url='http://stackoverflow.com')]
df = pd.DataFrame(data)

df['nameurl'] = df['name'] + '#' + df['url']
def make_clickable_both(val): 
    name, url = val.split('#')
    return f'<a target="_blank" href="{url}">{name}</a>'

st.dataframe(df.style.applymap(make_clickable_both, subset=['nameurl']))

st.dataframe(df.style.format({'nameurl': make_clickable_both}))

One way would be to use the to_html method in pandas and combine it with Streamlit’s options for injecting html. Though this would lose the interactivity of the pandas dataframe and make it a static table.

st.markdown(df.to_html(render_links=True),unsafe_allow_html=True)

Or if you want to render whatever html is in a cell, you can specify to not escape the characters (with or without rendering plain urls as links):

st.markdown(df.to_html(render_links=True, escape=False),unsafe_allow_html=True)

I see in the documentation that there is experimental support for pandas styler, but I don’t know off the bat how it behaves with styling links since Streamlit is a bit specific about how it accepts and displays html. I’m playing around with it right now and will post again if I find something.

This is probably the best idea. Apparently, it can also be done using Ag-Grid (check the related issue here).


Another option is to render the dataframe as a plotly table, as it allows for some basic HTML like hyperlinks.

plotlytable

Code:
import streamlit as st
import pandas as pd
import plotly.graph_objects as go

def create_link(url:str) -> str:
    return f'''<a href="{url}">🔗</a>'''

df = pd.DataFrame(
    {"Site": "DuckDuckGo Google Bing".split(),
     "URL": "https://duckduckgo.com/ https://www.google.com/ https://www.bing.com/".split()}
)

df['Link'] = [create_link(url) for url in df["URL"]]

"# Dataframe as a plotly table"

fig = go.Figure(
    data=[
        go.Table(
            columnwidth = [1,1,0.5],
            header=dict(
                values=[f"<b>{i}</b>" for i in df.columns.to_list()],
                fill_color='pink'
                ),
            cells=dict(
                values=df.transpose()
                )
            )
        ]
    )
st.plotly_chart(fig, use_container_width=True)

Thanks for your suggestion here. I’d like to make my table interactive and Ag-Grid seems like the option here, but I’ve never used it before. According to the reference you shared, it looks like it’s using Ag-Grid and importing javascript function to make the values in a specific column clickable. Do you happen to have a working example that would work in this example? Thanks so much for your help :slight_smile:

You are right. A JsCode instance is passed to the cellRendered kwarg. The JsCode is just a JS function that takes the content in the column and builds an HTML hyperlink tag:

function(params) { return '<a href=' + params.value + '> 🖱️ </a>' }

image

Code:
import streamlit as st
import pandas as pd
from st_aggrid import AgGrid, JsCode, GridOptionsBuilder

df = pd.DataFrame(
        {"Site": "DuckDuckGo Google Bing".split(),
        "URL": "https://duckduckgo.com/ https://www.google.com/ https://www.bing.com/".split()}
    )

gb = GridOptionsBuilder.from_dataframe(df)

gb.configure_column("URL",
                    headerName="URL",
                    cellRenderer=JsCode(
                        """
                        function(params) {
                            return '<a href=' + params.value + '> 🖱️ </a>'
                            }
                        """))

gridOptions = gb.build()

AgGrid(df, gridOptions=gridOptions, allow_unsafe_jscode=True)

With the latest Streamlit release (1.23) we added new column types that can be used with st.dataframe or st.data_editor. This also includes the LinkColumn which can just URLs as clickable hyperlinks:

import pandas as pd
import streamlit as st

data_df = pd.DataFrame(
    {
        "apps": [
            "https://roadmap.streamlit.app",
            "https://extras.streamlit.app",
            "https://issues.streamlit.app",
            "https://30days.streamlit.app",
        ],
    }
)

st.data_editor(
    data_df,
    column_config={
        "apps": st.column_config.LinkColumn("Trending apps")
    },
    hide_index=True,
)

image

It’s currently not possible to show a label instead of the URL, if you would like to do that as well you can upvote this feature request on Github.

Just updating this thread, it is possible now (version 1.30) to show a label instead of the URL :balloon:. column_config.LinkColumn takes the display_text parameter to format the text that is displayed in the cell.

image