Skip to content

Instantly share code, notes, and snippets.

@nathancooperjones
Last active February 17, 2023 04:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathancooperjones/cbee3ee7421f14d1b9fd1a56ec4f9874 to your computer and use it in GitHub Desktop.
Save nathancooperjones/cbee3ee7421f14d1b9fd1a56ec4f9874 to your computer and use it in GitHub Desktop.
df_to_html - ShopRunner's open-sourced helper function to convert Pandas DataFrame's to HTML.
import pandas as pd
def df_to_html(df: pd.DataFrame,
image_cols: List[str] = [],
hyperlink_cols: List[str] = [],
html_tags: Dict[str, Union[str, List[str]]] = dict(),
transpose: bool = False,
image_width: Optional[int] = None,
max_num_rows: int = 200,
**kwargs) -> str:
"""
Convert a Pandas DataFrame to HTML.
Parameters
-------------
df: DataFrame
DataFrame to convert to HTML
image_cols: str or list
Column names that contain image urls or file paths. Columns specified as images will make
all other transformations to those columns be ignored. Local files will display correctly in
Jupyter if specified using relative paths but not if specified using absolute paths (see
https://github.com/jupyter/notebook/issues/3810).
hyperlink_cols: str or list
Column names that contain hyperlinks to open in a new tab
html_tags: dictionary
A transformation to be inserted directly into the HTML tag.
Ex: ``{'col_name_1': 'strong'}`` becomes ``<strong>col_name_1</strong>``
Ex: ``{'col_name_2': 'mark'}`` becomes ``<mark>col_name_2</mark>``
Ex: ``{'col_name_3': 'h2'}`` becomes ``<h2>col_name_3</h2>``
Ex: ``{'col_name_4': ['em', 'strong']}`` becomes ``<em><strong>col_name_4</strong></em>``
transpose: bool
Transpose the DataFrame before converting to HTML
image_width: int
Set image width for each image generated
max_num_rows: int
Maximum number of rows to display
**kwargs: keyword arguments
Additional arguments sent to ``pandas.DataFrame.to_html``, as listed in:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_html.html
Returns
-------------
df_html: HTML
DataFrame converted to a HTML string, ready for displaying
Examples
-------------
In a Jupyter notebook:
.. code-block:: python
from IPython.core.display import display, HTML
import pandas as pd
df = pd.DataFrame({
'item': ['Beefy Fritos® Burrito'],
'price': ['1.00'],
'image_url': ['https://www.tacobell.com/images/22480_beefy_fritos_burrito_269x269.jpg'],
})
display(
HTML(
df_to_html(
df,
image_cols='image_url',
html_tags={'item': 'strong', 'price': 'em'},
image_width=200,
)
)
)
Notes
-------------
Converted table will have CSS class 'dataframe', unless otherwise specified.
"""
def _wrap_cols_if_needed(cols: [str, List[str]]) -> List[str]:
"""Necessary for columns named with integers."""
try:
iter(cols)
except TypeError:
cols = [cols]
if isinstance(cols, str):
cols = [cols]
return cols
if max_num_rows is None or len(df) <= max_num_rows:
df = df.copy() # copy the dataframe so we don't edit the original!
else:
# explicit copy eliminates a warning we don't need
df = df.head(max_num_rows).copy()
image_cols = _wrap_cols_if_needed(image_cols)
for image_col in image_cols:
if image_col not in df.columns:
raise ValueError('{} not a column in df!'.format(image_col))
if not image_width:
df[image_col] = df[image_col].map(lambda x: f'<img src="{x}">')
else:
df[image_col] = df[image_col].map(lambda x: f'<img src="{x}" width={image_width}>')
hyperlink_cols = _wrap_cols_if_needed(hyperlink_cols)
for hyperlink_col in hyperlink_cols:
if hyperlink_col not in df.columns:
raise ValueError('{} not a column in df!'.format(hyperlink_col))
if hyperlink_col in image_cols:
continue
df[hyperlink_col] = (
df[hyperlink_col].map(lambda x: f'<a target="_blank" href="{x}">{x}</a>')
)
for col, transformations in html_tags.items():
if col not in df.columns:
raise ValueError(f'{col} not a column in df!')
if col in image_cols:
continue
if isinstance(transformations, str):
transformations = [transformations]
opening_tag = ''
for extra in transformations:
opening_tag += f'<{extra}>'
closing_tag = ''
for extra in transformations[::-1]:
closing_tag += f'</{extra}>'
df[col] = df[col].map(lambda x: f'{opening_tag}{x}{closing_tag}')
max_colwidth = pd.get_option('display.max_colwidth')
if pd.__version__ != '0':
# this option is not backwards compatible with Pandas v1.0.0
pd.set_option('display.max_colwidth', None)
else:
pd.set_option('display.max_colwidth', -1)
if transpose:
df = df.T
df_html = df.to_html(escape=False, **kwargs)
pd.set_option('display.max_colwidth', max_colwidth)
return df_html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment