Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compat with jupyter's new HTML table style #15379

Closed
jorisvandenbossche opened this issue Feb 12, 2017 · 21 comments
Closed

Compat with jupyter's new HTML table style #15379

jorisvandenbossche opened this issue Feb 12, 2017 · 21 comments
Labels
Output-Formatting __repr__ of pandas objects, to_string
Milestone

Comments

@jorisvandenbossche
Copy link
Member

See also discussion in jupyterlab/jupyterlab#961

With the upcoming notebook 5.0 release and in current jupyterlab, jupyter has a new (much better!) default HTML table styling. The only problem is that it fixes the width of columns hardcoded at 150 px.

IMO this is a problem. Not the default as such, but the fact that you cannot easily change this when you want to see long table content. The result is that when having cells/column names with long content (and sometimes you deliberately create such cells/column names), it is impossible to inspect those data with the default repr.
Only solutions are to inspect specifics such as df.values or df.columns.

Another consequence is that the pd.options.display.max_colwidth option becomes useless.

Possible way forward:

  • override the max-width for our html repr's to set it to 'none' (@TomAugspurger shows here that this is possible: New table style truncates columns jupyterlab/jupyterlab#961 (comment))
  • if we like the more narrow default, we can always decrease the default for pd.options.display.max_colwidth (currently 50 chars) at the same time. The the default looks similar to jupyter's one, but you have still the ability to adjust it with our options.
@jorisvandenbossche jorisvandenbossche added the Output-Formatting __repr__ of pandas objects, to_string label Feb 12, 2017
@jorisvandenbossche jorisvandenbossche added this to the 0.20.0 milestone Feb 12, 2017
@jorisvandenbossche
Copy link
Member Author

The overriding can be done by adding the following style to each _repr_html_:

<style type="text/css">
  table.dataframe td, table.dataframe th {
    max-width: none;
  }
</style>

Other options could be:

  • see all data on hover
  • wrap longer cells

@jorisvandenbossche
Copy link
Member Author

Another issue is that, IMO, we should keep some kind of wrapping long text in multiple lines, see eg the notebook here: http://nbviewer.jupyter.org/gist/epifanio/e82443b79c24ceb2d59ba49cad9a62d4 (from gitter).
Even if you can use pd.options.display.max_colwidth to set it to a really high number eg 1000, this is only useful if the long text is wrapped over multiple lines, and not on one gigantic line (as you would get with current jupyterlab/notebook master.

@jorisvandenbossche
Copy link
Member Author

In the meantime, my proposal to remove the max-width in jupyter has been accepted, so we can close this issue!

We can still adjust our pd.options.display.max_colwidth default value of 50 if people like the less wide default look of the tables. (cc @TomAugspurger)

@jorisvandenbossche jorisvandenbossche modified the milestones: No action, 0.20.0 Feb 27, 2017
@jorisvandenbossche
Copy link
Member Author

Reopening this because there are some other issues we have to think about as well. What I encountered now are the display of MultiIndexes:

Due to the right-alignment instead of left alignment, multi-indexed columns get a bit strange:

screenshot from 2017-02-28 16-07-58

Also multi-indexer rows are not ideal because the distinction between the levels is not always clear (the borders are gone, but the shading does not always differ depending on the number of rows in the level).

In this case, that is OK:

screenshot from 2017-02-28 16-08-18

But in the following the shading is the same (and certainly when having more rows in one level label, or different number of rows for different labels, it becomes difficult to see the border between the level labels):

screenshot from 2017-02-28 16-09-01

@TomAugspurger
Copy link
Contributor

Good catch. Would we be better of vertical-aligning the row MultiIndex? We'll also want to check the interaction with index-level names (I'm getting caught up on things, should have more time to look myself towards the end of the week).

@jorisvandenbossche
Copy link
Member Author

Level names are generally OK I think, see for example:

screenshot from 2017-02-28 16-55-33

The question is a bit if there is a general solution that improves this that we can propose to jupyter, or whether we try to solve this on the pandas side with some custom formatting.

@jorisvandenbossche
Copy link
Member Author

jorisvandenbossche commented Feb 28, 2017

For the row multi-index, vertical alignment to the top seems better:

screenshot from 2017-02-28 17-00-34

The strange thing is that I see <th rowspan="3" valign="top">A</th> for that row header, so we already included the notion that we want it to align at the top, only that does not seem to work.
-> EDIT: "The valign attribute of <th> is not supported in HTML5. Use CSS instead." So we could replace that with <th style="vertical-align:top"> if we only want to fix it specifically for the multi-index

@joshij1979
Copy link

I s there any option to disable the default styling .. basically i want to roll back to previous default settings..

@TomAugspurger
Copy link
Contributor

TomAugspurger commented Apr 13, 2017 via email

@jorisvandenbossche
Copy link
Member Author

For the MultiIndex issues (from the above comments), I opened an issue on the jupyter side: jupyter/notebook#2408 (and ideas what would be the best solution for the multi-indexed columns is also welcome ..)

@jorisvandenbossche jorisvandenbossche modified the milestones: 0.20.0, No action Apr 16, 2017
@jorisvandenbossche
Copy link
Member Author

@TomAugspurger any ideas what we could do for the multi-index columns?
Easiest would be to switch back to left-alignment instead of right-alignment, but that would be a pity for normal frames without multi-index

@TomAugspurger
Copy link
Contributor

@TomAugspurger any ideas what we could do for the multi-index columns?

Looking now. I think we'll need to adjust the generated HTML to add some classes to the ths in a MI.

@TomAugspurger
Copy link
Contributor

I think if we left-align any levels, then we have to do them all.

screen shot 2017-04-18 at 6 25 58 am

@TomAugspurger
Copy link
Contributor

This isn't too bad:

screen shot 2017-04-18 at 6 57 23 am

I'm going to play around with borders to see how that looks with right-alignment.

@TomAugspurger
Copy link
Contributor

OK, putting together a PR now. Here's an example notebook comparing master and the PR https://gist.github.com/79f032afa4e498f86a9d59905d0f6fbd
You'll have to download it since nbviewer doesn't have the new styling.

Changes:

  1. MultiIndex column headers are all left-aligned (this is only for MI, single-level column headers are still right-aligned)
  2. MuliIndex row labels are top top-aligned

screen shot 2017-04-20 at 9 41 53 pm
screen shot 2017-04-20 at 9 41 59 pm

@donnaaboise
Copy link

@TomAugspurger I have noticed that MultiIndex row labels are top-aligned in the default display, but are middle-aligned when used with DataFrame.style.format(). For example :

image

compared with

image

I find the top aligned row labels much easier to read (although I can see the appeal of the middle-aligned labels). Is there a way to get top-aligned labels when using style.format ?

@TomAugspurger
Copy link
Contributor

TomAugspurger commented Feb 23, 2019 via email

@donnaaboise
Copy link

On your hint, I looked at what df.to_html() produces (in the default case) to find the right CSS attribute.

  <tbody>
    <tr>
      <th rowspan="6" valign="top">A</th>
      <th rowspan="2" valign="top">a</th>
      <th>1</th>
      <td>-0.010034</td>
      <td>-0.035311</td>
    </tr>

Looks like I need to set th with something like :

df.style.set_table_styles([{"selector":"th", "props":[("valign","top")] } ])

But this didn't work. I must be missing something on how to set these properties.

@donnaaboise
Copy link

I just tried the following:

th_prop = {"selector":"th", "props":[("vertical-align","top")] }
df.style.format('{:.2f}'.format).set_table_styles([th_prop])

which works. It isn't obvious how to make a more global change, though.


@TomAugspurger
Copy link
Contributor

TomAugspurger commented Feb 23, 2019 via email

@ycopin
Copy link

ycopin commented Mar 30, 2020

Any news on this issue, or a related one? I still wonder why a simple df.style.format("{:.2f}") should change the vertical alignment of multi-rows, or how I could simply avoid it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Output-Formatting __repr__ of pandas objects, to_string
Projects
None yet
Development

No branches or pull requests

5 participants