From 3878bd28bd1442442e7a5822ef8ec38db297699f Mon Sep 17 00:00:00 2001 From: Jim Stearns Date: Mon, 22 May 2017 15:40:09 -0700 Subject: [PATCH 1/2] BUG: Render empty DataFrame as empty HTML table w/o raising IndexError. --- pandas/io/formats/style.py | 37 ++++++++++++++------------- pandas/tests/io/formats/test_style.py | 6 +++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index eac82ddde2318..3d7e0fcdc69b3 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -238,24 +238,25 @@ def format_attr(pair): "class": " ".join(cs), "is_visible": True}) - for c, value in enumerate(clabels[r]): - cs = [COL_HEADING_CLASS, "level%s" % r, "col%s" % c] - cs.extend(cell_context.get( - "col_headings", {}).get(r, {}).get(c, [])) - es = { - "type": "th", - "value": value, - "display_value": value, - "class": " ".join(cs), - "is_visible": _is_visible(c, r, col_lengths), - } - colspan = col_lengths.get((r, c), 0) - if colspan > 1: - es["attributes"] = [ - format_attr({"key": "colspan", "value": colspan}) - ] - row_es.append(es) - head.append(row_es) + if clabels: + for c, value in enumerate(clabels[r]): + cs = [COL_HEADING_CLASS, "level%s" % r, "col%s" % c] + cs.extend(cell_context.get( + "col_headings", {}).get(r, {}).get(c, [])) + es = { + "type": "th", + "value": value, + "display_value": value, + "class": " ".join(cs), + "is_visible": _is_visible(c, r, col_lengths), + } + colspan = col_lengths.get((r, c), 0) + if colspan > 1: + es["attributes"] = [ + format_attr({"key": "colspan", "value": colspan}) + ] + row_es.append(es) + head.append(row_es) if self.data.index.names and not all(x is None for x in self.data.index.names): diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index ee7356f12f498..5511b82de544e 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -103,6 +103,12 @@ def test_render(self): s.render() # it worked? + def test_render_empty_df(self): + empty_df = DataFrame() + es = Styler(empty_df) + es.render() + # It didn't raise IndexError? + def test_render_double(self): df = pd.DataFrame({"A": [0, 1]}) style = lambda x: pd.Series(["color: red; border: 1px", From d9c354dcd2b8c172ccc5d6dd4e20520eb5195225 Mon Sep 17 00:00:00 2001 From: Jim Stearns Date: Tue, 23 May 2017 07:56:55 -0700 Subject: [PATCH 2/2] TST: Test rendering of 2 empty-ish DataFrames (#15953) DataFrame with an index but no column, and one with a column but no index. Add entry to whatsnew. --- doc/source/whatsnew/v0.20.2.txt | 1 + pandas/tests/io/formats/test_style.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index 57625b725ddba..6813518bdd9ec 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -54,6 +54,7 @@ I/O ^^^ - Bug that would force importing of the clipboard routines unnecessarily, potentially causing an import error on startup (:issue:`16288`) +- Bug that raised IndexError HTML-rendering an empty DataFrame (:issue:`15953`) Plotting diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 5511b82de544e..9911888f758fb 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -103,11 +103,15 @@ def test_render(self): s.render() # it worked? - def test_render_empty_df(self): + def test_render_empty_dfs(self): empty_df = DataFrame() es = Styler(empty_df) es.render() - # It didn't raise IndexError? + # An index but no columns + DataFrame(columns=['a']).style.render() + # A column but no index + DataFrame(index=['a']).style.render() + # No IndexError raised? def test_render_double(self): df = pd.DataFrame({"A": [0, 1]})