From 0aeadbb05a103b0861ef87d404c4233a594f1676 Mon Sep 17 00:00:00 2001 From: Sylvain Lannuzel Date: Mon, 10 Aug 2020 08:58:00 +0200 Subject: [PATCH 1/5] reformat begin and end table --- pandas/io/formats/latex.py | 106 ++++++++++++------------------------- 1 file changed, 34 insertions(+), 72 deletions(-) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 5d6f0a08ef2b5..970bd0a147b1d 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -121,10 +121,7 @@ def pad_empties(x): else: column_format = self.column_format - if self.longtable: - self._write_longtable_begin(buf, column_format) - else: - self._write_tabular_begin(buf, column_format) + self._write_longtable_begin(buf, column_format) buf.write("\\toprule\n") @@ -190,10 +187,7 @@ def pad_empties(x): if self.multirow and i < len(strrows) - 1: self._print_cline(buf, i, len(strcols)) - if self.longtable: - self._write_longtable_end(buf) - else: - self._write_tabular_end(buf) + self._write_longtable_end(buf) def _format_multicolumn(self, row: List[str], ilevels: int) -> List[str]: r""" @@ -288,7 +282,7 @@ def _write_tabular_begin(self, buf, column_format: str): for 3 columns """ if self._table_float: - # then write output in a nested table/tabular environment + # then write output in a nested table/tabular or longtable environment if self.caption is None: caption_ = "" else: @@ -304,12 +298,30 @@ def _write_tabular_begin(self, buf, column_format: str): else: position_ = f"[{self.position}]" - buf.write(f"\\begin{{table}}{position_}\n\\centering{caption_}{label_}\n") + if self.longtable: + table_ = f"\\begin{{longtable}}{position_}{{{column_format}}}" + tabular_ = "" + else: + table_ = f"\\begin{{table}}{position_}\n\\centering" + tabular_ = f"\n\\begin{{tabular}}{{{column_format}}}\n" + + if self.longtable and ( + self.caption is not None or self.label is not None): + # a double-backslash is required at the end of the line + # as discussed here: + # https://tex.stackexchange.com/questions/219138 + backlash_ = "\\\\\n" + elif self.longtable and self.position is not None: + backlash_ = "\n" + else: + backlash_ = "" + buf.write(f"{table_}{caption_}{label_}{backlash_}{tabular_}") else: - # then write output only in a tabular environment - pass - - buf.write(f"\\begin{{tabular}}{{{column_format}}}\n") + if self.longtable: + tabletype_ = "longtable" + else: + tabletype_ = "tabular" + buf.write(f"\\begin{{{tabletype_}}}{{{column_format}}}\n") def _write_tabular_end(self, buf): """ @@ -323,62 +335,12 @@ def _write_tabular_end(self, buf): a string. """ - buf.write("\\bottomrule\n") - buf.write("\\end{tabular}\n") - if self._table_float: - buf.write("\\end{table}\n") - else: - pass - - def _write_longtable_begin(self, buf, column_format: str): - """ - Write the beginning of a longtable environment including caption and - label if provided by user. - - Parameters - ---------- - buf : string or file handle - File path or object. If not specified, the result is returned as - a string. - column_format : str - The columns format as specified in `LaTeX table format - `__ e.g 'rcl' - for 3 columns - """ - if self.caption is None: - caption_ = "" - else: - caption_ = f"\\caption{{{self.caption}}}" - - if self.label is None: - label_ = "" - else: - label_ = f"\\label{{{self.label}}}" - - if self.position is None: - position_ = "" + if self.longtable: + buf.write("\\end{longtable}\n") else: - position_ = f"[{self.position}]" - - buf.write( - f"\\begin{{longtable}}{position_}{{{column_format}}}\n{caption_}{label_}" - ) - if self.caption is not None or self.label is not None: - # a double-backslash is required at the end of the line - # as discussed here: - # https://tex.stackexchange.com/questions/219138 - buf.write("\\\\\n") - - @staticmethod - def _write_longtable_end(buf): - """ - Write the end of a longtable environment. - - Parameters - ---------- - buf : string or file handle - File path or object. If not specified, the result is returned as - a string. - - """ - buf.write("\\end{longtable}\n") + buf.write("\\bottomrule\n") + buf.write("\\end{tabular}\n") + if self._table_float: + buf.write("\\end{table}\n") + else: + pass From 7fcb5f8e5353e14b4c04ee334028361a39940f8f Mon Sep 17 00:00:00 2001 From: Sylvain Lannuzel Date: Mon, 10 Aug 2020 09:12:52 +0200 Subject: [PATCH 2/5] typo --- pandas/io/formats/latex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 970bd0a147b1d..35c45babd4965 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -121,7 +121,7 @@ def pad_empties(x): else: column_format = self.column_format - self._write_longtable_begin(buf, column_format) + self._write_tabular_begin(buf, column_format) buf.write("\\toprule\n") @@ -187,7 +187,7 @@ def pad_empties(x): if self.multirow and i < len(strrows) - 1: self._print_cline(buf, i, len(strcols)) - self._write_longtable_end(buf) + self._write_tabular_end(buf) def _format_multicolumn(self, row: List[str], ilevels: int) -> List[str]: r""" From a795a571032eff3dcfbd533baa67000eca7274f5 Mon Sep 17 00:00:00 2001 From: Sylvain Lannuzel Date: Mon, 10 Aug 2020 09:13:57 +0200 Subject: [PATCH 3/5] change test to add newline --- pandas/tests/io/formats/test_to_latex.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index 93ad3739e59c7..96a9ed2b86cf4 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -555,7 +555,8 @@ def test_to_latex_longtable_caption_label(self): result_cl = df.to_latex(longtable=True, caption=the_caption, label=the_label) expected_cl = r"""\begin{longtable}{lrl} -\caption{a table in a \texttt{longtable} environment}\label{tab:longtable}\\ +\caption{a table in a \texttt{longtable} environment} +\label{tab:longtable}\\ \toprule {} & a & b \\ \midrule From 1074b39ff9fa01bdac15baa493eb0aba33e5a5e1 Mon Sep 17 00:00:00 2001 From: Sylvain Lannuzel Date: Mon, 10 Aug 2020 09:17:35 +0200 Subject: [PATCH 4/5] black pandas reformat --- pandas/io/formats/latex.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 35c45babd4965..98721fc04de8b 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -305,8 +305,7 @@ def _write_tabular_begin(self, buf, column_format: str): table_ = f"\\begin{{table}}{position_}\n\\centering" tabular_ = f"\n\\begin{{tabular}}{{{column_format}}}\n" - if self.longtable and ( - self.caption is not None or self.label is not None): + if self.longtable and (self.caption is not None or self.label is not None): # a double-backslash is required at the end of the line # as discussed here: # https://tex.stackexchange.com/questions/219138 From 54f3f24713215b257cec849e2bde2e53158fbdda Mon Sep 17 00:00:00 2001 From: Sylvain Lannuzel Date: Mon, 10 Aug 2020 10:49:04 +0200 Subject: [PATCH 5/5] clearer backlash variable --- pandas/io/formats/latex.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 98721fc04de8b..715b8bbdf5672 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -300,7 +300,7 @@ def _write_tabular_begin(self, buf, column_format: str): if self.longtable: table_ = f"\\begin{{longtable}}{position_}{{{column_format}}}" - tabular_ = "" + tabular_ = "\n" else: table_ = f"\\begin{{table}}{position_}\n\\centering" tabular_ = f"\n\\begin{{tabular}}{{{column_format}}}\n" @@ -309,9 +309,7 @@ def _write_tabular_begin(self, buf, column_format: str): # a double-backslash is required at the end of the line # as discussed here: # https://tex.stackexchange.com/questions/219138 - backlash_ = "\\\\\n" - elif self.longtable and self.position is not None: - backlash_ = "\n" + backlash_ = "\\\\" else: backlash_ = "" buf.write(f"{table_}{caption_}{label_}{backlash_}{tabular_}")