Is there a way to apply a style to a pandas
table in Jupyter Lab and then print it while keeping the table truncation functionality?
I have large tables where both the columns and the rows are truncated automatically when printed to the output cells. I would like to retain this functionality and still use the formatting capability of a Styler
object, e.g., use a formatter to show up to two decimal places.
I would not like to use head()
, tail()
, or truncate()
. I would like keep the three dots that imply that the data shown is not the full table.
I also know that some pandas
display options, such as "chop", can change decimal formatting, but there are other kinds of formatting that I would like to apply, like formatting the index.
Is this possible?
For example:
import numpy as np
import pandas as pd
n_rows = 100
n_cols = 50
rng = np.random.default_rng()
data = rng.uniform(low=0., high=100., size=(n_rows, n_cols))
df = pd.DataFrame(data)
df
I would like it to be truncated like this:
– while applying a formatter like this:
df.style.format(formatter='{:.2f}')
I was able to come up with my own answer. The code is below.
Notes:
Styler
format.pandas
display options usually print the minimum number of rows and the maximum number of columns (no option display.min_columns
).I had some help from the thread StackOverflow: Merging Pandas styler object side by side.
from IPython.display import display, HTML
# Function
def style_with_truncation(df, formatter='{:.2f}', min_rows=10, max_columns=20):
half_rows = min_rows // 2
half_cols = max_columns // 2
# Left half
upper_left = df.iloc[:half_rows ,:half_cols].style.format(formatter=formatter)
lower_left = df.iloc[-half_rows:,:half_cols].style.format(formatter=formatter)
ellipsis_half_row_left = pd.DataFrame([['...'] * (half_cols)],
index=['...'], columns=upper_left.data.columns)
left_half = upper_left.concat(ellipsis_half_row_left.style).concat(lower_left)
# Right half
upper_right = df.iloc[:half_rows ,-half_cols:].style.format(formatter=formatter)
lower_right = df.iloc[-half_rows:,-half_cols:].style.format(formatter=formatter)
ellipsis_half_row_right = pd.DataFrame([['...'] * (half_cols)],
index=['...'], columns=upper_right.data.columns)
right_half = upper_right.concat(ellipsis_half_row_right.style).concat(lower_right)
# Middle
ellipsis_column = pd.DataFrame({'...' : ['...'] * (min_rows+1)}, columns=['...'])
ellipsis_column = ellipsis_column.style
# Set the Styler attribute to be shown side by side
left_half.set_table_attributes("style='display:inline'")
right_half.set_table_attributes("style='display:inline'")
ellipsis_column.set_table_attributes("style='display:inline'")
# Display the styler objects inline
row_col_text = f"<p>{df.shape[0]:d} rows × {df.shape[1]:d} columns</p>"
display(HTML(left_half._repr_html_() +
ellipsis_column.hide(axis="index")._repr_html_() +
right_half.hide(axis="index")._repr_html_()
+ row_col_text))
# Example of a function call
min_rows = pd.options.display.min_rows
max_columns = pd.options.display.max_columns
style_with_truncation(df, formatter='{:.2f}', min_rows=min_rows, max_columns=max_columns)