From 815872ee45fb46f93d5d42f9a6503bc159e10a95 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 15 Mar 2021 20:01:29 +0100 Subject: [PATCH 1/4] CLN: make `cell_context` DefaultDict like `ctx` - simplify code --- pandas/io/formats/style.py | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 3abb39d2194c0..d303e598703f8 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -193,7 +193,7 @@ def __init__( self.hidden_index: bool = False self.hidden_columns: Sequence[int] = [] self.ctx: DefaultDict[Tuple[int, int], CSSList] = defaultdict(list) - self.cell_context: Dict[str, Any] = {} + self.cell_context: DefaultDict[Tuple[int, int], str] = defaultdict(str) self._todo: List[Tuple[Callable, Tuple, Dict]] = [] self.tooltips: Optional[_Tooltips] = None def_precision = get_option("display.precision") @@ -418,19 +418,11 @@ def _translate(self): if clabels: for c, value in enumerate(clabels[r]): - cs = [ - COL_HEADING_CLASS, - f"level{r}", - f"col{c}", - ] - cs.extend( - cell_context.get("col_headings", {}).get(r, {}).get(c, []) - ) es = { "type": "th", "value": value, "display_value": value, - "class": " ".join(cs), + "class": f"{COL_HEADING_CLASS} level{r} col{c}", "is_visible": _is_visible(c, r, col_lengths), } colspan = col_lengths.get((r, c), 0) @@ -490,7 +482,6 @@ def _translate(self): row_es.append(es) for c, value in enumerate(row_tup[1:]): - cs = [DATA_CLASS, f"row{r}", f"col{c}"] formatter = self._display_funcs[(r, c)] row_dict = { "type": "td", @@ -503,12 +494,14 @@ def _translate(self): # only add an id if the cell has a style props: CSSList = [] if self.cell_ids or (r, c) in ctx: - row_dict["id"] = "_".join(cs[1:]) + row_dict["id"] = f"row{r}_col{c}" props.extend(ctx[r, c]) # add custom classes from cell context - cs.extend(cell_context.get("data", {}).get(r, {}).get(c, [])) - row_dict["class"] = " ".join(cs) + cls = "" + if (r, c) in cell_context: + cls = " " + cell_context[r, c] + row_dict["class"] = f"{DATA_CLASS} row{r} col{c}{cls}" row_es.append(row_dict) if props: # (), [] won't be in cellstyle_map, cellstyle respectively @@ -722,15 +715,10 @@ def set_td_classes(self, classes: DataFrame) -> Styler: """ classes = classes.reindex_like(self.data) - mask = (classes.isna()) | (classes.eq("")) - self.cell_context["data"] = { - r: { - c: [str(classes.iloc[r, c])] - for c, cn in enumerate(classes.columns) - if not mask.iloc[r, c] - } - for r, rn in enumerate(classes.index) - } + for r, row_tup in enumerate(classes.itertuples()): + for c, value in enumerate(row_tup[1:]): + if not (pd.isna(value) or value == ""): + self.cell_context[(r, c)] = str(value) return self @@ -845,7 +833,7 @@ def clear(self) -> None: """ self.ctx.clear() self.tooltips = None - self.cell_context = {} + self.cell_context.clear() self._todo = [] def _compute(self): From 96ff79fc3a318e366fa9cc9c33ab1f1be3632659 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sat, 20 Mar 2021 07:49:23 +0100 Subject: [PATCH 2/4] update styler benchmarks --- asv_bench/benchmarks/io/style.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/asv_bench/benchmarks/io/style.py b/asv_bench/benchmarks/io/style.py index 4fc07bbabda06..39588fa86d000 100644 --- a/asv_bench/benchmarks/io/style.py +++ b/asv_bench/benchmarks/io/style.py @@ -14,15 +14,21 @@ def setup(self, cols, rows): columns=[f"float_{i+1}" for i in range(cols)], index=[f"row_{i+1}" for i in range(rows)], ) - self._style_apply() - def time_render(self, cols, rows): + def time_apply_render(self, cols, rows): + self._style_apply() self.st.render() - def peakmem_apply(self, cols, rows): + def peakmem_apply_render(self, cols, rows): self._style_apply() + self.st.render() - def peakmem_render(self, cols, rows): + def time_classes_render(self, cols, rows): + self._style_classes() + self.st.render() + + def peakmem_classes_render(self, cols, rows): + self._style_classes() self.st.render() def _style_apply(self): @@ -32,3 +38,8 @@ def _apply_func(s): ] self.st = self.df.style.apply(_apply_func, axis=1) + + def _style_classes(self): + classes = self.df.apply(lambda v: ("cls-1" if v > 0 else "")) + classes = DataFrame(classes, index=self.index, columns=self.columns) + self.st = self.df.style.set_td_classes(classes) From c425dddae4b5d19de598257f1e5113dc9dba2731 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sat, 20 Mar 2021 08:01:16 +0100 Subject: [PATCH 3/4] update styler benchmarks --- asv_bench/benchmarks/io/style.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asv_bench/benchmarks/io/style.py b/asv_bench/benchmarks/io/style.py index 39588fa86d000..fae6daf2c0387 100644 --- a/asv_bench/benchmarks/io/style.py +++ b/asv_bench/benchmarks/io/style.py @@ -40,6 +40,6 @@ def _apply_func(s): self.st = self.df.style.apply(_apply_func, axis=1) def _style_classes(self): - classes = self.df.apply(lambda v: ("cls-1" if v > 0 else "")) - classes = DataFrame(classes, index=self.index, columns=self.columns) + classes = self.df.applymap(lambda v: ("cls-1" if v > 0 else "")) + classes.index, classes.columns = self.df.index, self.df.columns self.st = self.df.style.set_td_classes(classes) From 0151db547b311fa4c0b18f3591cd6e35a28c6d8d Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sat, 20 Mar 2021 08:09:12 +0100 Subject: [PATCH 4/4] update styler benchmarks --- asv_bench/benchmarks/io/style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asv_bench/benchmarks/io/style.py b/asv_bench/benchmarks/io/style.py index fae6daf2c0387..6c0ca6fac6ec3 100644 --- a/asv_bench/benchmarks/io/style.py +++ b/asv_bench/benchmarks/io/style.py @@ -3,7 +3,7 @@ from pandas import DataFrame -class RenderApply: +class Render: params = [[12, 24, 36], [12, 120]] param_names = ["cols", "rows"]