Skip to content

Commit 98c8146

Browse files
committed
Merge pull request #5374 from bjornarneson/patch-1
Escape special characters in to_latex() output
2 parents d7c6801 + 2a84de2 commit 98c8146

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Improvements to existing features
8787
- perf improvments in ``dtypes/ftypes`` methods (:issue:`5968`)
8888
- perf improvments in indexing with object dtypes (:issue:`5968`)
8989
- improved dtype inference for ``timedelta`` like passed to constructors (:issue:`5458`,:issue:`5689`)
90+
- escape special characters when writing to latex (:issue: `5374`)
9091

9192
.. _release.bug_fixes-0.13.1:
9293

pandas/core/format.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,15 @@ def write(buf, frame, column_format, strcols):
468468
for i, row in enumerate(zip(*strcols)):
469469
if i == nlevels:
470470
buf.write('\\midrule\n') # End of header
471-
crow = [(x.replace('_', '\\_')
471+
crow = [(x.replace('\\', '\\textbackslash') # escape backslashes first
472+
.replace('_', '\\_')
472473
.replace('%', '\\%')
474+
.replace('$', '\\$')
475+
.replace('#', '\\#')
476+
.replace('{', '\\{')
477+
.replace('}', '\\}')
478+
.replace('~', '\\textasciitilde')
479+
.replace('^', '\\textasciicircum')
473480
.replace('&', '\\&') if x else '{}') for x in row]
474481
buf.write(' & '.join(crow))
475482
buf.write(' \\\\\n')

pandas/tests/test_format.py

+24
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,30 @@ def test_to_latex(self):
16541654
\end{tabular}
16551655
"""
16561656
self.assertEqual(withoutindex_result, withoutindex_expected)
1657+
1658+
def test_to_latex_escape_special_chars(self):
1659+
special_characters = ['&','%','$','#','_',
1660+
'{','}','~','^','\\']
1661+
df = DataFrame(data=special_characters)
1662+
observed = df.to_latex()
1663+
expected = r"""\begin{tabular}{ll}
1664+
\toprule
1665+
{} & 0 \\
1666+
\midrule
1667+
0 & \& \\
1668+
1 & \% \\
1669+
2 & \$ \\
1670+
3 & \# \\
1671+
4 & \_ \\
1672+
5 & \{ \\
1673+
6 & \} \\
1674+
7 & \textasciitilde \\
1675+
8 & \textasciicircum \\
1676+
9 & \textbackslash \\
1677+
\bottomrule
1678+
\end{tabular}
1679+
"""
1680+
self.assertEqual(observed, expected)
16571681

16581682
class TestSeriesFormatting(tm.TestCase):
16591683
_multiprocess_can_split_ = True

0 commit comments

Comments
 (0)