23

The pandas option max_colwidth controls how many characters will be included in the repr of a dataframe:

import string, random
import pandas as pd
df = pd.DataFrame([''.join(random.choice(string.ascii_lowercase + ' ') for j in range(1000)) for i in range(4)])

pd.options.display.max_colwidth = 10
print(df)

yields

           0
0  lmftge...
1  pqttqb...
2  wi wgy...
3  ow dip...

and

pd.options.display.max_colwidth = 30
print(df)

yields

                               0
0  lmftgenioerszvgzfaxorzciow...
1  pqttqbqqe pykgguxnjsspbcti...
2  wi wgybtgcbxkobrwnaxpxwsjc...
3  ow dippaiamvvcofvousieckko...

And you can set pd.options.display.max_colwidth = 0 to remove the limit altogether. Fine so far!

But if the dataframe is rendered in HTML inside a notebook, the notebook will wrap the table of the column to the width of the display, regardless of this setting:

wrapped table

Is there any way to avoid this, i.e. to have the HTML table column rendered as wide as is necessary to fit the each row on a single line?

More generally, is it possible to control the width of HTML table columns in notebook output independent of the number of characters in the pandas output?

smci
  • 32,567
  • 20
  • 113
  • 146
mike
  • 4,901
  • 2
  • 19
  • 19
  • You could try writing your own child template as explained in the [`nbconvert` documentation](https://nbconvert.readthedocs.io/en/latest/customizing.html). I'm not familiar enough with templates to write an answer, but [here is the parent template](https://github.com/jupyter/nbconvert/blob/master/nbconvert/templates/html/full.tpl) you would use. – IanS Jun 09 '16 at 07:36
  • I have added a few tags in case someone following those can help... – IanS Jun 09 '16 at 07:38
  • Look at the approaches where people use custom CSS. Be aware however that's a one-size-fits-all for all Jupyter HTML output, so the sizing would have to be ridiculously small to render that 500?-char line without wrapping. So, the short answer is I doubt this is practical. – smci Nov 18 '16 at 14:26

3 Answers3

20

Building on Ben's answer, but without needing to go into the custom css files, which work differently for juptyter lab.

Just put this in a cell and run it:

%%html
<style>
.dataframe td {
    white-space: nowrap;
}
</style>
SnowFrogger
  • 296
  • 3
  • 4
7

If you make a file: ~/.jupyter/custom$ atom custom.css and then put this in it:

.dataframe td {
    white-space: nowrap;
}

Then it will force the cell to show as one line, but then you get a scrolling table.

enter image description here

If you want it to not scroll, then set:

div.output_subarea {
    overflow-x: inherit;
}

and then it'll be as wide as it needs to be:

enter image description here

It's not super pretty, but I'm sure that you can tidy it up if needs be.

I found this very helpful. You'll also need to restart the notebook after you first create the css file for it to register, but from then on you can just refresh the page to see the changes to the css take effect.

This was the notebook that I was testing on.

Community
  • 1
  • 1
Ben
  • 12,614
  • 4
  • 37
  • 69
  • The "actual question" answer does indeed work for me. If you want to get rid of the answer to the "opposite" question (while retaining the corrected path to `~/.jupyter/custom/custom.css`) then I'd be glad to mark it as the solution. – mike Feb 15 '17 at 05:53
  • 1
    Is the `$ atom ` in the middle of `~/.jupyter/custom$ atom custom.css` a typo? – mike Feb 16 '17 at 13:18
0

Another option if you prefer to do it with 1 line of code or if you need to have different formats in different parts of your notebook, is to use Pandas Styler:

dfs = df.style.set_table_styles([dict(selector="td", props=[('white-space', 'nowrap')])])
display(dfs)

It is based on CSS so if in the middle of the notebook you want to go back to the previous format, you can write:

dfs = df.style.set_table_styles([dict(selector="td", props=[('overflow', 'hidden'),  
                      ('text-overflow', 'ellipsis'), ('max-width', '120px')])])
rehaqds
  • 414
  • 2
  • 6