8000 ENH: `Styler.apply(map)_index` made compatible with `Styler.to_latex` by attack68 · Pull Request #41993 · pandas-dev/pandas · GitHub
[go: up one dir, main page]

Skip to content

ENH: Styler.apply(map)_index made compatible with Styler.to_latex #41993

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

Merged
merged 32 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ece8855
add apply across index
attack68 Jun 9, 2021
a3a88e5
add applymap across index
attack68 Jun 9, 2021
066e4f3
improve docs
attack68 Jun 9, 2021
50dbcc7
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jun 11, 2021
ef5839f
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jun 12, 2021
5e4c1c0
add column header styling and amend tests
attack68 Jun 12, 2021
20ac7e0
doc sharing
attack68 Jun 13, 2021
26c5340
doc fix
attack68 Jun 13, 2021
2437b72
doc fix
attack68 Jun 13, 2021
312a6e6
collapse the cellstyle maps
attack68 Jun 13, 2021
553426f
add basic test
attack68 Jun 13, 2021
f01dfee
add basic test
attack68 Jun 13, 2021
f940165
parametrise tests
attack68 Jun 13, 2021
6f5b46c
test for raises ValueError
attack68 Jun 13, 2021
75cf6ca
test html working
attack68 Jun 13, 2021
d654139
test html working
attack68 Jun 13, 2021
728091a
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jun 14, 2021
17787ef
whats new 1.4.0
attack68 Jun 14, 2021
c9882aa
make apply_header compatible with to_latex
attack68 Jun 14, 2021
248de0d
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jun 20, 2021
bf6cd10
Merge branch 'styler_apply_index_specific' into styler_apply_index_sp…
attack68 Jun 20, 2021
321458e
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jun 29, 2021
3d2e4bd
Merge branch 'styler_apply_index_specific' into styler_apply_index_sp…
attack68 Jun 29, 2021
ed58798
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jul 13, 2021
b58fc55
Merge branch 'styler_apply_index_specific' into styler_apply_index_sp…
attack68 Jul 13, 2021
8d8e88f
update tests
attack68 Jul 14, 2021
e17d766
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Jul 30, 2021
e0cec44
Merge branch 'styler_apply_index_specific' into styler_apply_index_sp…
attack68 Jul 30, 2021
f70bf65
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Aug 6, 2021
42457de
Merge branch 'styler_apply_index_specific' into styler_apply_index_sp…
attack68 Aug 6, 2021
7ede8cc
Merge remote-tracking branch 'upstream/master' into styler_apply_inde…
attack68 Aug 12, 2021
57ce478
format tests
attack68 Aug 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doc/source/reference/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ Style application
Styler.applymap
Styler.apply_header
Styler.applymap_header
Styler.where
Styler.format
Styler.hide_index
Styler.hide_columns
Expand Down
47 changes: 18 additions & 29 deletions pandas/io/formats/style_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,39 +322,20 @@ def _translate_header(
_element("th", blank_class, blank_value, not self.hide_index_)
] * (self.data.index.nlevels - 1)

name = self.data.columns.names[r]
column_name = [
_element(
"th",
f"{blank_class if name is None else index_name_class} level{r}",
name if name is not None else blank_value,
not self.hidden_index,
)
]

if clabels:
column_headers = []
for c, value in enumerate(clabels[r]):
header_element = _element(
name = self.data.columns.names[r]
column_name = [
_element(
"th",
f"{blank_class if name is None else index_name_class} level{r}",
name if name is not None else blank_value,
not self.hide_index_,
)

if self.cell_ids:
header_element["id"] = f"level{r}_col{c}"
if (r, c) in self.ctx_columns and self.ctx_columns[r, c]:
header_element["id"] = f"level{r}_col{c}"
self.cellstyle_map_columns[
tuple(self.ctx_columns[r, c])
].append(f"level{r}_col{c}")

column_headers.append(header_element)
]

if clabels:
column_headers = [
_element(
column_headers = []
for c, value in enumerate(clabels[r]):
header_element = _element(
"th",
f"{col_heading_class} level{r} col{c}",
value,
Expand All @@ -365,8 +346,16 @@ def _translate_header(
else ""
),
)
for c, value in enumerate(clabels[r])
]

if self.cell_ids:
header_element["id"] = f"level{r}_col{c}"
if (r, c) in self.ctx_columns and self.ctx_columns[r, c]:
header_element["id"] = f"level{r}_col{c}"
self.cellstyle_map_columns[
tuple(self.ctx_columns[r, c])
].append(f"level{r}_col{c}")

column_headers.append(header_element)

if len(self.data.columns) > max_cols:
# add an extra column with `...` value to indicate trimming
Expand Down Expand Up @@ -505,7 +494,7 @@ def _translate_body(
"th",
f"{row_heading_class} level{c} row{r}",
value,
(_is_visible(r, c, idx_lengths) and not self.hidden_index),
(_is_visible(r, c, idx_lengths) and not self.hide_index_),
attributes=(
f'rowspan="{idx_lengths.get((c, r), 0)}"'
if idx_lengths.get((c, r), 0) > 1
Expand Down
143 changes: 143 additions & 0 deletions pandas/tests/io/formats/style/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,149 @@ def test_caption_as_sequence(styler):
assert "<caption>full cap</caption>" in styler.render()


@pytest.mark.parametrize("index", [False, True])
@pytest.mark.parametrize("columns", [False, True])
def test_sticky_basic(styler, index, columns):
if index:
styler.set_sticky(axis=0)
if columns:
styler.set_sticky(axis=1)

res = styler.set_uuid("").to_html()
cs1 = "tbody th {\n position: sticky;\n left: 0px;\n background-color: white;\n}"
assert (cs1 in res) is index
cs2 = "thead th {\n position: sticky;\n top: 0px;\n background-color: white;\n}"
assert (cs2 in res) is columns


@pytest.mark.parametrize("index", [False, True])
@pytest.mark.parametrize("columns", [False, True])
def test_sticky_mi(styler_mi, index, columns):
if index:
styler_mi.set_sticky(axis=0)
if columns:
styler_mi.set_sticky(axis=1)

res = styler_mi.set_uuid("").to_html()
assert (
(
dedent(
"""\
#T_ tbody th.level0 {
position: sticky;
left: 0px;
min-width: 75px;
max-width: 75px;
background-color: white;
}
"""
)
in res
)
is index
)
assert (
(
dedent(
"""\
#T_ tbody th.level1 {
position: sticky;
left: 75px;
min-width: 75px;
max-width: 75px;
background-color: white;
}
"""
)
in res
)
is index
)
assert (
(
dedent(
"""\
#T_ thead th.level0 {
position: sticky;
top: 0px;
height: 25px;
background-color: white;
}
"""
)
in res
)
is columns
)
assert (
(
dedent(
"""\
#T_ thead th.level1 {
position: sticky;
top: 25px;
height: 25px;
background-color: white;
}
"""
)
in res
)
is columns
)


@pytest.mark.parametrize("index", [False, True])
@pytest.mark.parametrize("columns", [False, True])
def test_sticky_levels(styler_mi, index, columns):
if index:
styler_mi.set_sticky(axis=0, levels=[1])
if columns:
styler_mi.set_sticky(axis=1, levels=[1])

res = styler_mi.set_uuid("").to_html()
assert "#T_ tbody th.level0 {" not in res
assert "#T_ thead th.level0 {" not in res
assert (
(
dedent(
"""\
#T_ tbody th.level1 {
position: sticky;
left: 0px;
min-width: 75px;
max-width: 75px;
background-color: white;
}
"""
)
in res
)
is index
)
assert (
(
dedent(
"""\
#T_ thead th.level1 {
position: sticky;
top: 0px;
height: 25px;
background-color: white;
}
"""
)
in res
)
is columns
)


def test_sticky_raises(styler):
with pytest.raises(ValueError, match="`axis` must be"):
styler.set_sticky(axis="bad")


@pytest.mark.parametrize("index", [True, False])
@pytest.mark.parametrize("columns", [True, False])
def test_applymap_header_cell_ids(styler, index, columns):
Expand Down
45 changes: 45 additions & 0 deletions pandas/tests/io/formats/style/test_to_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,51 @@ def test_short_caption(styler):
assert "\\caption[short cap]{full cap}" in result


@pytest.mark.parametrize(
"css, expected",
[
([("color", "red")], [("color", "{red}")]), # test color and input format types
(
[("color", "rgb(128, 128, 128 )")],
[("color", "[rgb]{0.502, 0.502, 0.502}")],
),
(
[("color", "rgb(128, 50%, 25% )")],
[("color", "[rgb]{0.502, 0.500, 0.250}")],
),
(
[("color", "rgba(128,128,128,1)")],
[("color", "[rgb]{0.502, 0.502, 0.502}")],
),
([("color", "#FF00FF")], [("color", "[HTML]{FF00FF}")]),
([("color", "#F0F")], [("color", "[HTML]{FF00FF}")]),
([("font-weight", "bold")], [("bfseries", "")]), # test font-weight and types
([("font-weight", "bolder")], [("bfseries", "")]),
([("font-weight", "normal")], []),
([("background-color", "red")], [("cellcolor", "{red}--lwrap")]),
(
[("background-color", "#FF00FF")], # test background-color command and wrap
[("cellcolor", "[HTML]{FF00FF}--lwrap")],
),
([("font-style", "italic")], [("itshape", "")]), # test font-style and types
([("font-style", "oblique")], [("slshape", "")]),
([("font-style", "normal")], []),
([("color", "red /*--dwrap*/")], [("color", "{red}--dwrap")]), # css comments
([("background-color", "red /* --dwrap */")], [("cellcolor", "{red}--dwrap")]),
],
)
def test_parse_latex_css_conversion(css, expected):
result = _parse_latex_css_conversion(css)
assert result == expected


def test_parse_latex_css_conversion_option():
css = [("command", "option--latex--wrap")]
expected = [("command", "option--wrap")]
result = _parse_latex_css_conversion(css)
assert result == expected


@pytest.mark.parametrize("index", [True, False])
@pytest.mark.parametrize("columns", [True, False])
def test_apply_map_header_render_mi(df, index, columns):
Expand Down
0