-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: add LaTeX math mode with parentheses #51903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mroeschke
merged 14 commits into
pandas-dev:main
from
natmokval:50040-add-math-mode-formatter-escape=latex-part2
Mar 31, 2023
Merged
Changes from 10 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
ba72f26
ENH: add math mode with parentheses
natmokval 0801f6a
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval 2320fb3
ENH: add math mode with parentheses II
natmokval c20e795
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval 2e283a7
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval 29e357c
ENH: add math mode with parentheses III
natmokval 849bf36
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval 9be5c22
ENH: add an example to latex-math mode and a line to whatsnew
natmokval 7b4b53a
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval 25e6b1f
ENH: update docs for Styler: add description latex-math mode to escape
natmokval ed27582
improve code style
natmokval 3daf4d5
add an example to test and correct _escape_latex_math
natmokval 78dcdf8
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval c06695e
Merge branch 'main' into 50040-add-math-mode-formatter-escape=latex-p…
natmokval File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -988,8 +988,9 @@ def format( | |||||||||||||||||
``{``, ``}``, ``~``, ``^``, and ``\`` in the cell display string with | ||||||||||||||||||
LaTeX-safe sequences. | ||||||||||||||||||
Use 'latex-math' to replace the characters the same way as in 'latex' mode, | ||||||||||||||||||
except for math substrings, which start and end with ``$``. | ||||||||||||||||||
Escaping is done before ``formatter``. | ||||||||||||||||||
except for math substrings, which either are surrounded | ||||||||||||||||||
by two characters ``$`` or start with the character ``\(`` and | ||||||||||||||||||
end with ``\)``. Escaping is done before ``formatter``. | ||||||||||||||||||
|
||||||||||||||||||
.. versionadded:: 1.3.0 | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -1117,7 +1118,8 @@ def format( | |||||||||||||||||
2 & \textbf{\$\%\#} \\ | ||||||||||||||||||
\end{tabular} | ||||||||||||||||||
|
||||||||||||||||||
Using ``escape`` in 'latex-math' mode. | ||||||||||||||||||
Applying ``escape`` in 'latex-math' mode. In the example below | ||||||||||||||||||
we enter math mode using the character ``$``. | ||||||||||||||||||
|
||||||||||||||||||
>>> df = pd.DataFrame([[r"$\sum_{i=1}^{10} a_i$ a~b $\alpha \ | ||||||||||||||||||
... = \frac{\beta}{\zeta^2}$"], ["%#^ $ \$x^2 $"]]) | ||||||||||||||||||
|
@@ -1129,6 +1131,34 @@ def format( | |||||||||||||||||
1 & \%\#\textasciicircum \space $ \$x^2 $ \\ | ||||||||||||||||||
\end{tabular} | ||||||||||||||||||
|
||||||||||||||||||
We can use the character ``\(`` to enter math mode and the character ``\)`` | ||||||||||||||||||
to close math mode. | ||||||||||||||||||
|
||||||||||||||||||
>>> df = pd.DataFrame([[r"\(\sum_{i=1}^{10} a_i\) a~b \(\alpha \ | ||||||||||||||||||
... = \frac{\beta}{\zeta^2}\)"], ["%#^ \( \$x^2 \)"]]) | ||||||||||||||||||
>>> df.style.format(escape="latex-math").to_latex() | ||||||||||||||||||
... # doctest: +SKIP | ||||||||||||||||||
\begin{tabular}{ll} | ||||||||||||||||||
& 0 \\ | ||||||||||||||||||
0 & \(\sum_{i=1}^{10} a_i\) a\textasciitilde b \(\alpha | ||||||||||||||||||
= \frac{\beta}{\zeta^2}\) \\ | ||||||||||||||||||
1 & \%\#\textasciicircum \space \( \$x^2 \) \\ | ||||||||||||||||||
\end{tabular} | ||||||||||||||||||
|
||||||||||||||||||
If we have in one DataFrame cell a combination of both shorthands | ||||||||||||||||||
for math formulas, the shorthand with the sign ``$`` will be applied. | ||||||||||||||||||
|
||||||||||||||||||
>>> df = pd.DataFrame([[r"\( x^2 \) $x^2$"], \ | ||||||||||||||||||
... [r"$\frac{\beta}{\zeta}$ \(\frac{\beta}{\zeta}\)"]]) | ||||||||||||||||||
>>> df.style.format(escape="latex-math").to_latex() | ||||||||||||||||||
... # doctest: +SKIP | ||||||||||||||||||
\begin{tabular}{ll} | ||||||||||||||||||
& 0 \\ | ||||||||||||||||||
0 & \textbackslash ( x\textasciicircum 2 \textbackslash ) $x^2$ \\ | ||||||||||||||||||
1 & $\frac{\beta}{\zeta}$ \textbackslash (\textbackslash | ||||||||||||||||||
frac\{\textbackslash beta\}\{\textbackslash zeta\}\textbackslash ) \\ | ||||||||||||||||||
\end{tabular} | ||||||||||||||||||
|
||||||||||||||||||
Pandas defines a `number-format` pseudo CSS attribute instead of the `.format` | ||||||||||||||||||
method to create `to_excel` permissible formatting. Note that semi-colons are | ||||||||||||||||||
CSS protected characters but used as separators in Excel's format string. | ||||||||||||||||||
|
@@ -2361,13 +2391,13 @@ def _escape_latex(s): | |||||||||||||||||
) | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def _escape_latex_math(s): | ||||||||||||||||||
def _math_mode_with_dollar(s): | ||||||||||||||||||
r""" | ||||||||||||||||||
All characters between two characters ``$`` are preserved. | ||||||||||||||||||
All characters in LaTeX math mode are preserved. | ||||||||||||||||||
|
||||||||||||||||||
The substrings in LaTeX math mode, which start with the character ``$`` | ||||||||||||||||||
and end with ``$``, are preserved without escaping. Otherwise | ||||||||||||||||||
regular LaTeX escaping applies. See ``_escape_latex()``. | ||||||||||||||||||
The substrings in LaTeX math mode, which start with | ||||||||||||||||||
the character ``$`` and end with ``$``, are preserved | ||||||||||||||||||
without escaping. Otherwise regular LaTeX escaping applies. | ||||||||||||||||||
|
||||||||||||||||||
Parameters | ||||||||||||||||||
---------- | ||||||||||||||||||
|
@@ -2392,3 +2422,79 @@ def _escape_latex_math(s): | |||||||||||||||||
|
||||||||||||||||||
res.append(_escape_latex(s[pos : len(s)])) | ||||||||||||||||||
return "".join(res).replace(r"rt8§=§7wz", r"\$") | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def _math_mode_with_parentheses(s): | ||||||||||||||||||
r""" | ||||||||||||||||||
All characters in LaTeX math mode are preserved. | ||||||||||||||||||
|
||||||||||||||||||
The substrings in LaTeX math mode, which start with | ||||||||||||||||||
the character ``\(`` and end with ``\)``, are preserved | ||||||||||||||||||
without escaping. Otherwise regular LaTeX escaping applies. | ||||||||||||||||||
|
||||||||||||||||||
Parameters | ||||||||||||||||||
---------- | ||||||||||||||||||
s : str | ||||||||||||||||||
Input to be escaped | ||||||||||||||||||
|
||||||||||||||||||
Return | ||||||||||||||||||
------ | ||||||||||||||||||
str : | ||||||||||||||||||
Escaped string | ||||||||||||||||||
""" | ||||||||||||||||||
s = s.replace(r"\(", r"LEFT§=§6yzLEFT").replace(r"\)", r"RIGHTab5§=§RIGHT") | ||||||||||||||||||
res = [] | ||||||||||||||||||
for item in re.split(r"LEFT§=§6yz|ab5§=§RIGHT", s): | ||||||||||||||||||
if item.startswith("LEFT") and item.endswith("RIGHT"): | ||||||||||||||||||
res.append(item.replace("LEFT", r"\(").replace("RIGHT", r"\)")) | ||||||||||||||||||
elif "LEFT" in item and "RIGHT" in item: | ||||||||||||||||||
res.append( | ||||||||||||||||||
_escape_latex(item).replace("LEFT", r"\(").replace("RIGHT", r"\)") | ||||||||||||||||||
) | ||||||||||||||||||
else: | ||||||||||||||||||
res.append( | ||||||||||||||||||
_escape_latex(item) | ||||||||||||||||||
.replace("LEFT", r"\textbackslash (") | ||||||||||||||||||
.replace("RIGHT", r"\textbackslash )") | ||||||||||||||||||
) | ||||||||||||||||||
return "".join(res) | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def _escape_latex_math(s): | ||||||||||||||||||
r""" | ||||||||||||||||||
All characters in LaTeX math mode are preserved. | ||||||||||||||||||
|
||||||||||||||||||
The substrings in LaTeX math mode, which either are surrounded | ||||||||||||||||||
by two characters ``$`` or start with the character ``\(`` and end with ``\)``, | ||||||||||||||||||
are preserved without escaping. Otherwise regular LaTeX escaping applies. | ||||||||||||||||||
|
||||||||||||||||||
Parameters | ||||||||||||||||||
---------- | ||||||||||||||||||
s : str | ||||||||||||||||||
Input to be escaped | ||||||||||||||||||
|
||||||||||||||||||
Return | ||||||||||||||||||
------ | ||||||||||||||||||
str : | ||||||||||||||||||
Escaped string | ||||||||||||||||||
""" | ||||||||||||||||||
s = s.replace(r"\$", r"rt8§=§7wz") | ||||||||||||||||||
pattern_d = re.compile(r"\$.*?\$") | ||||||||||||||||||
pattern_p = re.compile(r"\(.*?\)") | ||||||||||||||||||
pos_d = 0 | ||||||||||||||||||
pos_p = 0 | ||||||||||||||||||
ps_d = pattern_d.search(s, pos_d) | ||||||||||||||||||
ps_p = pattern_p.search(s, pos_p) | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you, I completely agree. I applied this change in the next commit. I did it locally and pushed the commit. |
||||||||||||||||||
mode = [] | ||||||||||||||||||
if ps_d: | ||||||||||||||||||
mode.append(ps_d.span()[0]) | ||||||||||||||||||
if ps_p: | ||||||||||||||||||
mode.append(ps_p.span()[0]) | ||||||||||||||||||
if len(mode) == 0: | ||||||||||||||||||
return _escape_latex(s.replace(r"\$", r"rt8§=§7wz")) | ||||||||||||||||||
if s[mode[0]] == r"$": | ||||||||||||||||||
return _math_mode_with_dollar(s.replace(r"\$", r"rt8§=§7wz")) | ||||||||||||||||||
if s[mode[0] - 1 : mode[0] + 1] == r"\(": | ||||||||||||||||||
return _math_mode_with_parentheses(s.replace(r"\$", r"rt8§=§7wz")) | ||||||||||||||||||
else: | ||||||||||||||||||
return _escape_latex(s.replace(r"\$", r"rt8§=§7wz")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this code.
You are replacing the string
\$
with a uuid string, first.Then, you are searching for a pattern (
r"\$.*?\$"
) that cannot exist, since it was replaced.Then in line 2490 you are replacing the same string
s
again with the same uuid, but this is unnecessary since it has already done this in line 2481.I think your tests pass and this does the correct thing but I think some of these lines are redundant and do nothing for the overall effect??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the comment.
It’s right, the replacement in line 2490 has a mistake. The right one would be the reverse replacement:
s.replace(r"rt8§=§7wz", r"\$")
I can explain what I am trying to do. When I checked the function
_escape_latex_math
I noticed that for a string like r"$&%#^$" which contains only one sign "$" and only one combination "\$" I got a wrong result, because the function processed this string in math mode. By doing the replacement in line 2481 I exclude from the consideration the string “\$” to avoid confusing it with “$”. Then I get the correct result and do the reverse replacement. If we don’t have a combination of one sign "$" and one sign "\$" we don’t need to do this check, but I prefer to leave it.I corrected my mistake a made a new commit. I also added an example for this case in the test.