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}))
1 Like

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)
2 Likes

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)
2 Likes

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.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.

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

1 Like