46

I'd like to insert a link (to a web page) inside a Pandas table, so when it is displayed in an IPython notebook, I could press the link.

I tried the following:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(range(5), columns=['a'])

In [3]: df['b'] = df['a'].apply(lambda x: 'http://example.com/{0}'.format(x))

In [4]: df
Out[4]:
   a                     b
0  0  http://example.com/0
1  1  http://example.com/1
2  2  http://example.com/2
3  3  http://example.com/3
4  4  http://example.com/4

But the URL is just displayed as text.

I also tried using an IPython HTML object:

In [5]: from IPython.display import HTML

In [6]: df['b'] = df['a'].apply(lambda x:HTML('http://example.com/{0}'.format(x)))

In [7]: df
Out[7]:
   a                                                 b
0  0  <IPython.core.display.HTML object at 0x0481E530>
1  1  <IPython.core.display.HTML object at 0x0481E770>
2  2  <IPython.core.display.HTML object at 0x0481E7B0>
3  3  <IPython.core.display.HTML object at 0x0481E810>
4  4  <IPython.core.display.HTML object at 0x0481EA70>

But it will only display the repr of the object.

Any other ideas?


alko got the right answer. I just wanted to add that the cell width is limited by default, and long HTML code will be truncated, i.e.:

<a href="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0">xxx</a>

will become this:

<a href="aaaaaaaaaaaaaaaaaaaaaa...

and won't be displayed correctly. (Even though the text xxx is short and can fit in the cell.)

I've bypassed it by setting:

pd.set_printoptions(max_colwidth=-1)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
lev
  • 3,986
  • 4
  • 33
  • 46

4 Answers4

73

I suppose you have to represent whole Pandas object as an HTML object, that is

In [1]: from IPython.display import HTML

In [2]: df = pd.DataFrame(list(range(5)), columns=['a'])

In [3]: df['a'] = df['a'].apply(lambda x: '<a href="http://example.com/{0}">link</a>'.format(x))

In [4]: HTML(df.to_html(escape=False))

Sorry, now I don't have IPython at hand, and can't check whether the output is correct.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alko
  • 46,136
  • 12
  • 94
  • 102
  • 1
    I can confirm that it does work (using anconda 4.2.0)! Thanks @alko. – Tarrasch Oct 13 '16 at 04:01
  • 12
    I noticed that for somewhat long urls, pandas "silently" shortens the html so that "blank" is displayed in the cells. Here's a solution: http://stackoverflow.com/q/26277757/621449 – Tarrasch Oct 13 '16 at 04:26
  • This method truncates any link longer than about 35 chars, which means the link rendering doesn't work... any idea how to get around this/ – conner.xyz Jul 11 '17 at 17:16
  • Was able to find answer here https://stackoverflow.com/questions/25351968/how-to-display-full-non-truncated-dataframe-information-in-html-when-convertin – conner.xyz Jul 11 '17 at 17:19
9

Since version 24, Pandas has a native way to deal with links: pandas.DataFrame.to_html

This works:

df["col"] = df["col"].apply( # insert links
            lambda x: "<a href='https://link{}'>{}</a>".format(
                re.findall("pattern", x)[0], x
            )
        )

df.to_html(
    render_links=True,
    escape=False,
)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Claudiu Creanga
  • 8,031
  • 10
  • 71
  • 110
6

If you want to avoid the issue of shortening the long urls you can also display the links with unique or standard values i.e.

df['Url'] = '<a href=' + df['Url'] + '><div>' + df['Name'] + '</div></a>'

df = df.to_html(escape=False)

# OR

df['Url'] = '<a href=' + df['Url'] + '><div>'Hello World'</div></a>'

df = df.to_html(escape=False)
Display name
  • 753
  • 10
  • 28
0

Install pretty-html-table

from pretty_html_table import build_table

body = """
<html>
<head>
</head>

<body>
        {0}
</body>

</html>
""".format(build_table(df, 'blue_light'))

You need not have to worry about the formatting and also of the website links in your DataFrame, the output will be with hyperlinks only.

Nisrin Dhoondia
  • 145
  • 1
  • 10