Yves
Yves

Reputation: 47

permantly apply style.format to a DataFrame

I went to apply a style.format to one of my columns in the df (to add commas), but after calling df second time –– it seems that the style.format is not permanent? When I do assign the style.format to a variable and then call it, it does work. BUT calling df.head(5) gives me AttributeError: 'Styler' object has no attribute 'head'

import pandas as pd
pd.set_option('display.max_rows', 10)
df = pd.read_excel('./resources/mycopy-copy.xlsx')
df <---#truncates here
df.style.format({'Number of Doses Procured': '{:,}'}) #or df = df.style.format({'Number of Doses Procured': '{:,}'})
df <---#spits out all 500 rows

Upvotes: 4

Views: 4519

Answers (1)

Pierre D
Pierre D

Reputation: 26221

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.

Upvotes: 3

Related Questions