Skip to content

Commit e81e96e

Browse files
committed
BUG: do not escape empty placeholder in to_latex()
closes #18667
1 parent fdba133 commit e81e96e

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

doc/source/whatsnew/v0.22.0.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ I/O
302302
- Bug in :func:`read_msgpack` with a non existent file is passed in Python 2 (:issue:`15296`)
303303
- Bug in :func:`read_csv` where a ``MultiIndex`` with duplicate columns was not being mangled appropriately (:issue:`18062`)
304304
- Bug in :func:`read_sas` where a file with 0 variables gave an ``AttributeError`` incorrectly. Now it gives an ``EmptyDataError`` (:issue:`18184`)
305-
-
305+
- Bug in :func:`DataFrame.to_latex()` where pairs of braces meant to serve as invisible placeholders were escaped (:issue:`18667`)
306306
-
307307

308308
Plotting

pandas/io/formats/format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ def get_col_type(dtype):
967967
.replace('#', '\\#').replace('{', '\\{')
968968
.replace('}', '\\}').replace('~', '\\textasciitilde')
969969
.replace('^', '\\textasciicircum').replace('&', '\\&')
970-
if x else '{}') for x in row]
970+
if (x and x != '{}') else '{}') for x in row]
971971
else:
972972
crow = [x if x else '{}' for x in row]
973973
if self.bold_rows and self.fmt.index:

pandas/tests/io/formats/test_to_latex.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,35 @@ def test_to_latex_no_bold_rows(self):
536536
\end{tabular}
537537
"""
538538
assert observed == expected
539+
540+
@pytest.mark.parametrize('name0', [None, 'named'])
541+
@pytest.mark.parametrize('name1', [None, 'named'])
542+
@pytest.mark.parametrize('axes', [[0], [1], [0, 1]])
543+
def test_to_latex_multiindex_names(self, name0, name1, axes):
544+
# GH 18667
545+
names = [name0, name1]
546+
mi = pd.MultiIndex.from_product([[1, 2], [3, 4]])
547+
df = pd.DataFrame(-1, index=mi.copy(), columns=mi.copy())
548+
for idx in axes:
549+
df.axes[idx].names = names
550+
551+
idx_names = tuple(n or '{}' for n in names)
552+
idx_names_row = ('%s & %s & & & & \\\\\n' % idx_names
553+
if (0 in axes and any(names)) else '')
554+
placeholder = '{}' if any(names) and 1 in axes else ' '
555+
col_names = [n if (bool(n) and 1 in axes) else placeholder
556+
for n in names]
557+
observed = df.to_latex()
558+
expected = r"""\begin{tabular}{llrrrr}
559+
\toprule
560+
& %s & \multicolumn{2}{l}{1} & \multicolumn{2}{l}{2} \\
561+
& %s & 3 & 4 & 3 & 4 \\
562+
%s\midrule
563+
1 & 3 & -1 & -1 & -1 & -1 \\
564+
& 4 & -1 & -1 & -1 & -1 \\
565+
2 & 3 & -1 & -1 & -1 & -1 \\
566+
& 4 & -1 & -1 & -1 & -1 \\
567+
\bottomrule
568+
\end{tabular}
569+
""" % tuple(list(col_names) + [idx_names_row])
570+
assert observed == expected

0 commit comments

Comments
 (0)