@@ -989,6 +989,8 @@ def format(
989989 Use 'latex' to replace the characters ``&``, ``%``, ``$``, ``#``, ``_``,
990990 ``{``, ``}``, ``~``, ``^``, and ``\`` in the cell display string with
991991 LaTeX-safe sequences.
992+ Use 'latex-math' to replace the characters the same way as in 'latex' mode,
993+ except for math substrings, which start and end with ``$``.
992994 Escaping is done before ``formatter``.
993995
994996 .. versionadded:: 1.3.0
@@ -1105,16 +1107,28 @@ def format(
11051107 <td .. >NA</td>
11061108 ...
11071109
1108- Using a ``formatter`` with LaTeX ``escape``.
1110+ Using a ``formatter`` with ``escape`` in 'latex' mode .
11091111
1110- >>> df = pd.DataFrame([["123"], ["~ ^"], ["$ %#"]])
1112+ >>> df = pd.DataFrame([["123"], ["~ ^"], ["%#"]])
11111113 >>> df.style.format("\\textbf{{{}}}", escape="latex").to_latex()
11121114 ... # doctest: +SKIP
11131115 \begin{tabular}{ll}
1114- {} & {0} \\
1116+ & 0 \\
11151117 0 & \textbf{123} \\
11161118 1 & \textbf{\textasciitilde \space \textasciicircum } \\
1117- 2 & \textbf{\$\%\#} \\
1119+ 2 & \textbf{\%\#} \\
1120+ \end{tabular}
1121+
1122+ Using ``escape`` in 'latex-math' mode.
1123+
1124+ >>> df = pd.DataFrame([[r"$\sum_{i=1}^{10} a_i$ a~b $\alpha \
1125+ ... = \frac{\beta}{\zeta^2}$"], ["%#^ $ \$x^2 $"]])
1126+ >>> df.style.format(escape="latex-math").to_latex()
1127+ ... # doctest: +SKIP
1128+ \begin{tabular}{ll}
1129+ & 0 \\
1130+ 0 & $\sum_{i=1}^{10} a_i$ a\textasciitilde b $\alpha = \frac{\beta}{\zeta^2}$ \\
1131+ 1 & \%\#\textasciicircum \space $ \$x^2 $ \\
11181132 \end{tabular}
11191133
11201134 Pandas defines a `number-format` pseudo CSS attribute instead of the `.format`
@@ -1743,9 +1757,12 @@ def _str_escape(x, escape):
17431757 return escape_html (x )
17441758 elif escape == "latex" :
17451759 return _escape_latex (x )
1760+ elif escape == "latex-math" :
1761+ return _escape_latex_math (x )
17461762 else :
17471763 raise ValueError (
1748- f"`escape` only permitted in {{'html', 'latex'}}, got { escape } "
1764+ f"`escape` only permitted in {{'html', 'latex', 'latex-math'}}, \
1765+ got { escape } "
17491766 )
17501767 return x
17511768
@@ -2344,3 +2361,36 @@ def _escape_latex(s):
23442361 .replace ("^" , "\\ textasciicircum " )
23452362 .replace ("ab2§=§8yz" , "\\ textbackslash " )
23462363 )
2364+
2365+
2366+ def _escape_latex_math (s ):
2367+ r"""
2368+ All characters between two characters ``$`` are preserved.
2369+
2370+ The substrings in LaTeX math mode, which start with the character ``$``
2371+ and end with ``$``, are preserved without escaping. Otherwise
2372+ regular LaTeX escaping applies. See ``_escape_latex()``.
2373+
2374+ Parameters
2375+ ----------
2376+ s : str
2377+ Input to be escaped
2378+
2379+ Return
2380+ ------
2381+ str :
2382+ Escaped string
2383+ """
2384+ s = s .replace (r"\$" , r"ab2§=§8yz" )
2385+ pattern = re .compile (r"\$.*?\$" )
2386+ pos = 0
2387+ ps = pattern .search (s , pos )
2388+ res = []
2389+ while ps :
2390+ res .append (_escape_latex (s [pos : ps .span ()[0 ]]))
2391+ res .append (ps .group ())
2392+ pos = ps .span ()[1 ]
2393+ ps = pattern .search (s , pos )
2394+
2395+ res .append (_escape_latex (s [pos : len (s )]))
2396+ return "" .join (res ).replace (r"ab2§=§8yz" , r"\$" )
0 commit comments