Pandas version checks

  • [X] I have checked that the issue still exists on the latest versions of the docs on main here

Location of the documentation

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_html.html

Documentation problem

Based on the doc str

Whether the generated HTML is for IPython Notebook.

I was expecting the generated HTML when setting notebook=True to look more similar in the browser to how the Styler looks looks in Jupyter.

import pandas as pd

df = pd.util.testing.makeDataFrame()

df.style.format("{:.2}").background_gradient(cmap="viridis").to_html(
    "notebook=False.html", notebook=False
)

df.style.format("{:.2}").background_gradient(cmap="viridis").to_html(
    "notebook=True.html", notebook=True
)

What I actually get is notebook=True.html and notebook=False.html looking identical.

Jupyter (expected) Browser actual (with notebook=True/False)
Screenshot 2022-11-28 at 17 10 58 Screenshot 2022-11-28 at 17 13 58

Suggested fix for documentation

Would be great if the doc string could be more specific on what effect setting to notebook=True is supposed to have.

Comment From: attack68

You are using Styler.to_html since df.style yields a Styler object. You are not using DataFrame.to_html.

Styler.to_html has no argument notebook and therefore it has no effect.

Comment From: janosh

Ah, my bad. Is it deliberately missing from Styler.to_html? If not, could this issue be reopened and turned into a feature request?

Comment From: attack68

Yes it is deliberately missing from Styler because it is an old argument that used to provide minor data alignment for text in columns. If you compare the output from DataFrame.to_html with the only difference visible in the HTML is,

<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
    .dataframe tbody tr th {
        vertical-align: top;
    }
    .dataframe thead th {
        text-align: right;
    }
</style>

Styler has a set_table_styles and other methods available to completely customise the entire table CSS, not just include this very specific block of code (which I believe is now out of date with the behaviour of newer Jupyter and Colab notebooks anyway).

You seem to be suggesting that notebook=True makes the HTML automatically look the same as the Jupyter notebook display. It doesn't. Jupyter has its own custom CSS for rendering tables within its cells. Different versions of Jupyter and Colab use different settings and will result in different looking tables. There is no point in creating a setting in pandas that attempts to copy the CSS styles of another software that can change their visual look in a new version. The objective is to give users the ability to define their own.

If you are interested in exploring some different CSS attrubute value pairs, here are those that JupyterNotebook attributes to tables, observed with Chrome element inspectior: Screenshot 2022-11-29 at 17 23 20

Comment From: janosh

You seem to be suggesting that notebook=True makes the HTML automatically look the same as the Jupyter notebook display.

Yes, that was my meaning.

It doesn't. Jupyter has its own custom CSS for rendering tables within its cells. Different versions of Jupyter and Colab use different settings and will result in different looking tables. There is no point in creating a setting in pandas that attempts to copy the CSS styles of another software that can change their visual look in a new version. The objective is to give users the ability to define their own.

I see, that's a fair point. Started using df.set_table_styles() last night but thought it a bit clunky:

styles = {
    "": [("font-family", "sans-serif"), ("border-collapse", "collapse")],
    "td, th": [
        ("border", "1px solid #ddd"),
        ("text-align", "left"),
        ("padding", "8px"),
    ],
}
df_styled.set_table_styles([dict(selector=sel, props=styles[sel]) for sel in styles])

This seems like a more natural syntax:

styles = {
    "": "font-family: sans-serif; border-collapse: collapse;",
    "td, th": "border: 1px solid #ddd; text-align: left; padding: 8px;",
}
df_styled.set_table_styles(styles)

But probably no interest in supporting that?

Anyway, final point: Maybe the notebook kwarg in df.to_html should be deprecated?

Comment From: attack68

As documented you can actually do this.

styles = {"": "color: red;", "th": "font-weight: bold;}
s.set_table_styles([{"selector": k, props: v} for k, v in styles.items()])

The dict version is reserved for allowing users to specific column only styles which is also useful.

A lot of things in df.to_html should be deprecated. It has been difficult to get concensus on changing the whole thing.

Comment From: janosh

Ah, I missed that CSS strings are supported. Should have tried that. Thanks for pointing it out.

The dict version is reserved for allowing users to specific column only styles which is also useful.

I see. There could be a flag as: Literal['columns', 'selectors']:

styles = {
    "": "font-family: sans-serif; border-collapse: collapse;",
    "td, th": "border: 1px solid #ddd; text-align: left; padding: 8px;",
}
df_styled.set_table_styles(styles, as='selectors')

styles = {
    "col_1": "background: black; color: white;",
    "col_2": "font-weight: bold;",
}
df_styled.set_table_styles(styles, as='columns')

Comment From: attack68

There could be, and actually that might even be better. But I'm not sure its better to introduce a new format after 6 years, with many stackoverflow questions following the current format. Also Im not sure we would get round to changing this before 2.0, which is the only sensible version where this change could be introduced.

Comment From: janosh

Should I open a new issue to discuss adding as: Literal['columns', 'selectors'] in v2?