I have to admit that my question and its title were incorrectly set and I have to close this topic:

pt.style.format({'percent_on_rent': '{:.0%}'})

code line in my code snippet returns pandas Styler object instance linked to its parent pandas DataFrame object instance. AFAIU when Jupiter Notebook code cell with such a code is run then Jupiter Notebook captures pandas Styler object instance and immediately formats it for output under the running cell while

print(pt)

prints pandas DataFrame object instance and how this object instance string(?) representation is obtained by the print(...) Python method and sent to standard(?) output and this standard output captured by Jupiter Notebook and rendered under the cell where the code is running can be probably found only in the Jupiter Notebook sources. Writing and running in a Jupiter Notebook cell the following code:

my_styler = pt.style.format({'percent_on_rent': '{:.0%}'})
my_styler

would be equivalent to just

pt.style.format({'percent_on_rent': '{:.0%}'})

while

my_styler = pt.style.format({'percent_on_rent': '{:.0%}'})
print(my_styler)

would output

<pandas.io.formats.style.Styler object at 0x...>

Here is a link on a topic of using pandas Styler object in Jupiter Notebook. More information could be googled.

Please correct me if I'm still wrong in this explanation.

Thanks!

[Update]

Here is a sample code, which demonstrates how to return pandas Styler object instance from Python methods and then output them in Jupiter Notebook using display(...) method:

import numpy as np
import pandas as pd

def rc1():
    return np.random.choice(['benzine', 'diesel', 'electro'])

def rc2():
    return 1 if np.random.choice([True, False]) else 0

def test_pandas_styler(caption):
    # fill list
    data = []
    for i in range(21): data.append([rc1(), rc2()])
       
    # make data frame
    df = pd.DataFrame(data, columns = ['engine_type', 'rented']) 
    
    # make pivot table
    pt = df.pivot_table(index=['engine_type'], values= ['rented'], aggfunc=[np.mean]).reset_index()
    pt.set_axis(['engine type', 'percent on rent'], axis = 'columns', inplace = True)
    
    # style pivot table
    st = pt.style.format({'percent on rent': '{:.0%}'}).hide_index()    
    st.set_table_styles([
           dict(selector="th", props=[('color', 'darkblue'), 
                                      ('vertical-align', 'top')]),
           dict(selector="th:first-child", props=[('max-width', '70px'), ('text-align', 'left')]),
           dict(selector="th:last-child", props=[('max-width', '50px')]),
           dict(selector="td:first-child", props=[('text-align', 'left')])
            ])    
    st.caption = caption
    
    return st

for f in [test_pandas_styler('Test {}'.format(i)) for i in range(1,4)]:
    display(f)

Answer from ShamilS on Stack Overflow
Top answer
1 of 1
2

I have to admit that my question and its title were incorrectly set and I have to close this topic:

pt.style.format({'percent_on_rent': '{:.0%}'})

code line in my code snippet returns pandas Styler object instance linked to its parent pandas DataFrame object instance. AFAIU when Jupiter Notebook code cell with such a code is run then Jupiter Notebook captures pandas Styler object instance and immediately formats it for output under the running cell while

print(pt)

prints pandas DataFrame object instance and how this object instance string(?) representation is obtained by the print(...) Python method and sent to standard(?) output and this standard output captured by Jupiter Notebook and rendered under the cell where the code is running can be probably found only in the Jupiter Notebook sources. Writing and running in a Jupiter Notebook cell the following code:

my_styler = pt.style.format({'percent_on_rent': '{:.0%}'})
my_styler

would be equivalent to just

pt.style.format({'percent_on_rent': '{:.0%}'})

while

my_styler = pt.style.format({'percent_on_rent': '{:.0%}'})
print(my_styler)

would output

<pandas.io.formats.style.Styler object at 0x...>

Here is a link on a topic of using pandas Styler object in Jupiter Notebook. More information could be googled.

Please correct me if I'm still wrong in this explanation.

Thanks!

[Update]

Here is a sample code, which demonstrates how to return pandas Styler object instance from Python methods and then output them in Jupiter Notebook using display(...) method:

import numpy as np
import pandas as pd

def rc1():
    return np.random.choice(['benzine', 'diesel', 'electro'])

def rc2():
    return 1 if np.random.choice([True, False]) else 0

def test_pandas_styler(caption):
    # fill list
    data = []
    for i in range(21): data.append([rc1(), rc2()])
       
    # make data frame
    df = pd.DataFrame(data, columns = ['engine_type', 'rented']) 
    
    # make pivot table
    pt = df.pivot_table(index=['engine_type'], values= ['rented'], aggfunc=[np.mean]).reset_index()
    pt.set_axis(['engine type', 'percent on rent'], axis = 'columns', inplace = True)
    
    # style pivot table
    st = pt.style.format({'percent on rent': '{:.0%}'}).hide_index()    
    st.set_table_styles([
           dict(selector="th", props=[('color', 'darkblue'), 
                                      ('vertical-align', 'top')]),
           dict(selector="th:first-child", props=[('max-width', '70px'), ('text-align', 'left')]),
           dict(selector="th:last-child", props=[('max-width', '50px')]),
           dict(selector="td:first-child", props=[('text-align', 'left')])
            ])    
    st.caption = caption
    
    return st

for f in [test_pandas_styler('Test {}'.format(i)) for i in range(1,4)]:
    display(f)

🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.io.formats.style.Styler.format.html
pandas.io.formats.style.Styler.format — pandas 3.0.1 documentation
>>> df = pd.DataFrame([ ... [r"\( x^2 \) $x^2$"], ... [r"$\frac{\beta}{\zeta}$ \(\frac{\beta}{\zeta}\)"]]) >>> df.style.format(escape="latex-math").to_latex() \begin{tabular}{ll} & 0 \\ 0 & \textbackslash ( x\textasciicircum 2 \textbackslash ) $x^2$ \\ 1 & $\frac{\beta}{\zeta}$ \textbackslash (\textbackslash frac\{\textbackslash beta\}\{\textbackslash zeta\}\textbackslash ) \\ \end{tabular} Pandas defines a number-format pseudo CSS attribute instead of the .format method to create to_excel permissible formatting. Note that semi-colons are CSS protected characters but used as separators in Excel’s format string.
Discussions

pandas - df.style.format() having no effect on dataframe - Stack Overflow
You may also be interested by this Q/A : Pandas : Set format for a single DataFrame. ... Sign up to request clarification or add additional context in comments. ... Thank you so very much. I did try removing the last df and showing the styler, but my IDE/Notebook (Pycharm) shows an object reference. More on stackoverflow.com
🌐 stackoverflow.com
.style.format not working in dataframe column
The examples here https://pandas.pydata.org/pandas-docs/stable/user_guide/style.html around #16 there is no value before the ‘:format specifier’. Did you try removing the random 0 from your {}? More on reddit.com
🌐 r/learnpython
7
2
December 27, 2019
Styler class doesn't apply formatting from Styler.format when writing to Excel
The desired behaviour should be ... with the Styler object should be written to the excel file just as it gets rendered in HTML. ... Excel document with formatting operations included. ... commit: None python: 2.7.13.final.0 python-bits: 64 OS: Darwin OS-release: 17.5.0 machine: x86_64 processor: i386 byteorder: little LC_ALL: None LANG: en_US.UTF-8 LOCALE: None.None · pandas: 0.23.0 pytest: ... More on github.com
🌐 github.com
5
May 26, 2018
python - problem of format while using pandas style - Stack Overflow
I'm currently using pandas style to custom my DataFrame before turning it into an HTML table. However, during my tests I'm getting quite the same error when I try to run my file : More on stackoverflow.com
🌐 stackoverflow.com
🌐
Pandas
pandas.pydata.org › docs › user_guide › style.html
Table Visualization — pandas documentation - PyData |
Use table styles where possible (e.g. for all cells or rows or columns at a time) since the CSS is nearly always more efficient than other formats. ... props = 'font-family: "Times New Roman", Times, serif; color: #e83e8c; font-size:1.3em;' df4.style.map(lambda x: props, subset=[1]) ... For large DataFrames where the same style is applied to many cells it can be more efficient to declare the styles as classes and then apply those classes to data cells, rather than directly applying styles to cells. It is, however, probably still easier to use the Styler function api when you are not concerned about optimization.
🌐
Reddit
reddit.com › r/learnpython › .style.format not working in dataframe column
r/learnpython on Reddit: .style.format not working in dataframe column
December 27, 2019 -

I am trying to add a '+' in front of positive numbers in one of the column in my dataframe. There are already negative numbers and zeros in the column. The column represents position changes and is automatically updated every 24hrs. Someone suggested I try the following -

df2.style.format({'Position Change':"{0:+g}"})

df2 is the name of the dataframe and Position Change is the name of the column. When I add the suggested code it does not change anything in the column, it also does not raise an error, so nothing happens. Can anyone help or know of another way to add + in front of a positive number in a column on a dataframe without doing it manually. Thanks

🌐
Stacked Turtles
kiwidamien.github.io › stylish-pandas.html
Stylish Pandas
November 6, 2019 - A trick I use to get around this is to use select_dtypes to select the numeric columns, and then use a dictionary comprehension to generate a dictionary with defaults, and then override the columns I want.
🌐
Practical Business Python
pbpython.com › styling-pandas.html
Stylin’ with Pandas - Practical Business Python
As you look at this data, it gets a bit challenging to understand the scale of the numbers because you have 6 decimal points and somewhat large numbers. Also, it is not immediately clear if this is in dollars or some other currency. We can fix that using the DataFrame style.format .
🌐
GitHub
github.com › pandas-dev › pandas › issues › 21221
Styler class doesn't apply formatting from Styler.format when writing to Excel · Issue #21221 · pandas-dev/pandas
May 26, 2018 - import pandas as pd df = pd.DataFrame({'a': [.1, .2], 'b': [.2, .3]}) df.style.background_gradient().format("{:.2%}").to_excel('test.xlsx') ... buf = StringIO() df = pd.DataFrame({'a': [.1, .2], 'b': [.2, .3]}) df.style.background_gradient().format("{:.2%}".format).to_excel(buf) buf.seek(0) pd.read_excel(buf) When reading the file the gradient will be applied correctly but the percentage formatting will not be.
Published   May 27, 2018
Author   HHammond
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 70767940 › problem-of-format-while-using-pandas-style
python - problem of format while using pandas style - Stack Overflow
I'm currently using pandas style to custom my DataFrame before turning it into an HTML table. However, during my tests I'm getting quite the same error when I try to run my file : <pandas.io.formats.style.Styler object at 0x7f987c016e20> I don't really understand what's going on since my code is really simple and the pandas documentation doesn't really help on that point.
🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.io.formats.style.Styler.format_index.html
pandas.io.formats.style.Styler.format_index — pandas 3.0.1 documentation
If the formatter argument is given in dict form but does not include all levels within the level argument then these unspecified levels will have the default formatter applied. Any levels in the formatter dict specifically excluded from the level argument will be ignored. When using a formatter string the dtypes must be compatible, otherwise a ValueError will be raised. ... Styler.format_index is ignored when using the output format Styler.to_excel, since Excel and Python have inherently different formatting structures.
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.18 › style.html
Style — pandas 0.18.1 documentation
For row and column slicing, any valid indexer to .loc will work. ... Only label-based slicing is supported right now, not positional. If your style function uses a subset or axis keyword argument, consider wrapping your function in a functools.partial, partialing out that keyword. ... We distinguish the display value from the actual value in Styler. To control the display value, the text is printed in each cell, use Styler.format.
Top answer
1 of 1
3

The short answer is: no, there is no way to "apply a style permanently to a DataFrame".

Styling is typically the last step before rendering (as HTML), although it can be composed by chaining.

The result of df.style.anyfunction() is a Style object. As such, it doesn't have the methods of DataFrame, in particular as per your question, .head():

>>> type(df.style.format('${:,.2f}'))
pandas.io.formats.style.Styler

The DataFrame doesn't know anything about any Styler. Instead, it is the Styler that has a reference to the DataFrame it was originally used for.

You can take the style itself and apply it to another DataFrame (with Styler.use() and Styler.export(), see below). However, regrettably, that doesn't seem to include .format() definitions (at least in pandas=1.2.1).

It's really too bad, because otherwise, it makes it quite easy to reuse a style for another DF (or df.head() per your example):

def neg_red(x):
    return f"color: {'red' if x < 0 else 'black'}"

df = pd.DataFrame(np.random.uniform(-4, 5, (5, 3)) * 1e4)
s = df.style.format('${:,.2f}').applymap(neg_red).highlight_max()
s

Observe that: assert vars(s)['data'] is df. So as I said above, the Styler object has a reference (data) to the DataFrame it was used on initially (so that, when it is asked to render, it knows what data to render).

Now, you can use the Styler object and apply it to another DataFrame (here: df.head(3)):

df.head(3).style.use(s.export())

As you can see, all the styling functions have been carried over, except for the formatting! I would imagine this is a bug or an oversight.

🌐
GitHub
github.com › pandas-dev › pandas › issues › 58737
BUG: "styler.format.thousands" option doesn't work for integers · Issue #58737 · pandas-dev/pandas
May 16, 2024 - I have checked that this issue has not already been reported. I have confirmed this bug exists on the latest version of pandas. I have confirmed this bug exists on the main branch of pandas. import pandas pandas.set_option('styler.format.thousands', ',') data = pandas.DataFrame(data=[{'field': 1234567890}], dtype='int64',) # Doesn't output integer field with comma separator data # Does output integer field with comma separator data.style.format(thousands=',')
Published   May 16, 2024
Author   vladpy8
🌐
CopyProgramming
copyprogramming.com › howto › pandas-dataframe-style-format-is-not-working
Pandas DataFrame Style Format Not Working? 2026 Guide to Latest Features & Best Practices
December 3, 2025 - While .style.format() is ignored during Excel export due to inherent formatting differences, pandas 2.3+ introduced the number-format pseudo-CSS attribute that forces Excel-compatible formatting.
🌐
Analytics Vidhya
analyticsvidhya.com › home › style your pandas dataframe and make it stunning
How to Style Pandas DataFrames for Better Visualization
April 4, 2025 - To plot such a mapping in the dataframe itself, there is no direct function but the “styler.background_gradient()” workaround does the work. ... cmap: By default, the “PuBu” colormap is selected by pandas You can create a custom matplotlib colormap and pass it to the camp parameter. axis: Generating heat plot via rows or columns criteria, by default: columns · text_color_threshold: Controls text visibility across varying background colors. As mentioned earlier also, the dataframe presented in the Jupyter notebooks is a table rendered using HTML and CSS.
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 1.5 › reference › api › pandas.io.formats.style.Styler.format.html
pandas.io.formats.style.Styler.format — pandas 1.5.2 documentation
>>> df = pd.DataFrame([["123"], ["~ ^"], ["$%#"]]) >>> df.style.format("\\textbf{{{}}}", escape="latex").to_latex() ... \begin{tabular}{ll} {} & {0} \\ 0 & \textbf{123} \\ 1 & \textbf{\textasciitilde \space \textasciicircum } \\ 2 & \textbf{\$\%\#} \\ \end{tabular} Pandas defines a number-format pseudo CSS attribute instead of the .format method to create to_excel permissible formatting. Note that semi-colons are CSS protected characters but used as separators in Excel’s format string.
🌐
Towards Data Science
towardsdatascience.com › home › latest › style pandas dataframe like a master
Style Pandas Dataframe Like a Master | Towards Data Science
January 21, 2025 - Pandas code to render the formatted dataframe without the index · df.head(10).style.format({"BasePay": "${:20,.0f}", "OtherPay": "${:20,.0f}", "TotalPay": "${:20,.0f}", "TotalPayBenefits":"${:20,.0f}"}) .format({"JobTitle": lambda x:x.lower(), "EmployeeName": lambda x:x.lower()}) .hide_index() Having this type of flexibility when it comes to rendering our dataset is pretty powerful and useful, but that simply put NOT ENOUGH.
🌐
GitHub
github.com › pandas-dev › pandas › issues › 23996
Dictionary of callables to df.style.format not behaving properly · Issue #23996 · pandas-dev/pandas
November 29, 2018 - The styler is not properly rendering based on column assignments as I would assume a similar table to the first using pipe.
Author   DeltaSigma130
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.18 › generated › pandas.formats.style.Styler.format.html
pandas.formats.style.Styler.format — pandas 0.18.1 documentation
The default display value for numeric values is the “general” (g) format with pd.options.display.precision precision. ... >>> df = pd.DataFrame(np.random.randn(4, 2), columns=['a', 'b']) >>> df.style.format("{:.2%}") >>> df['c'] = ['a', 'b', 'c', 'd'] >>> df.style.format({'C': str.upper})