-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Styler.apply(map)_index
made compatible with Styler.to_excel
#41995
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
ENH: Styler.apply(map)_index
made compatible with Styler.to_excel
#41995
Conversation
Styler.apply(map)_header
made compatible with Styler.to_excel
(for non-MultiIndex)
…x_specific # Conflicts: # doc/source/reference/style.rst # pandas/io/formats/style_render.py # pandas/tests/io/formats/style/test_html.py
…x_specific # Conflicts: # pandas/tests/io/formats/style/test_style.py
…x_specific_excel # Conflicts: # doc/source/whatsnew/v1.4.0.rst
pandas/io/formats/excel.py
Outdated
@@ -472,6 +472,7 @@ def __init__( | |||
self.na_rep = na_rep | |||
if not isinstance(df, DataFrame): | |||
self.styler = df | |||
self.styler._compute() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed? init doesn't do anything really except for set things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this clause is only called when you do styler.to_excel
. It needs _compute
to calculate the styles added. Previously, this was done in _generate_body
below, but, since, it is now needed for both body and headers I brought it to the obvious point: initialisation, to avoid having to unnecessarily do it twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could maybe move this to styler.to_excel
and maybe do the pre-calc there before passing to ExcelFormatter. Might be more sensible like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could maybe move this to styler.to_excel and maybe do the pre-calc there before passing to ExcelFormatter. Might be more sensible like that.
I tried it and it didn't work. The new tests failed when using a custom ExcelFormatter, the styles computation needs to be done within ExcelFormatter.
I discovered #25351 where basically the tests for So I have replaced these with a minimalist set of non-comprehensive tests, and also added the tests relevant to this PR. |
pandas/io/formats/excel.py
Outdated
@@ -582,7 +589,10 @@ def _format_header_mi(self) -> Iterable[ExcelCell]: | |||
# Format in legacy format with dots to indicate levels. | |||
for i, values in enumerate(zip(*level_strs)): | |||
v = ".".join(map(pprint_thing, values)) | |||
yield ExcelCell(lnum, coloffset + i + 1, v, self.header_style) | |||
if styles: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth making a function to do this conversion as this is repeated below
@@ -7,163 +7,158 @@ | |||
from pandas.io.excel import ExcelWriter | |||
from pandas.io.formats.excel import ExcelFormatter | |||
|
|||
pytest.importorskip("jinja2") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is essentially a new requirement for this right? its ok ,but let's fully document this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, actually this file only had one test and that test already had importskip("jinja2")
, so I haven't added anything, just moved it top level to share across all tests.
I noticed, however, that technically it is would be possible to create a Styler
, apply methods and then do .to_excel
all without jinja2
. The only problem is that Styler
does a check for jinja2
at initialisation, so this is not currently functionally possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its fine to require jinja2 for this, just mention this in the docs / doc-string somewhere. (pretty sure we should be testing this but pls ensure somewhere (and skipping elsewhere)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is an import error warning if jinja2 not present. But could be more explicit. Will do as a follow up.
@@ -472,12 +493,14 @@ def __init__( | |||
self.na_rep = na_rep | |||
if not isinstance(df, DataFrame): | |||
self.styler = df | |||
self.styler._compute() # calculate applied styles |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this need to be called? e.g. shouldn't this be in render?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok i see your expl. i guess this is fine.
@@ -7,163 +7,158 @@ | |||
from pandas.io.excel import ExcelWriter | |||
from pandas.io.formats.excel import ExcelFormatter | |||
|
|||
pytest.importorskip("jinja2") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its fine to require jinja2 for this, just mention this in the docs / doc-string somewhere. (pretty sure we should be testing this but pls ensure somewhere (and skipping elsewhere)
@jreback ping green |
…x_specific_excel # Conflicts: # doc/source/whatsnew/v1.4.0.rst
@@ -472,12 +493,14 @@ def __init__( | |||
self.na_rep = na_rep | |||
if not isinstance(df, DataFrame): | |||
self.styler = df | |||
self.styler._compute() # calculate applied styles |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok i see your expl. i guess this is fine.
thanks @attack68 |
This is a follow-on to #41893.
It makes the new
Styler.apply_index
andStyler.applymap_index
methods compatible withStyler.to_excel
. If the methods are not used the output reverts to the old format.MultiIndex Case
NOTE on TESTS
The tests for styler_to_excel were broken and were xfailed out of production in 2019. Since they dont work I have replaced them with some other, cleaner, tests and add tests relevant to this PR also.
Closes #25351