Using Python sympy in a Python code chunk in RMarkdown

I was recently asked about using sympy in Python to print \(LaTeX\) formulas in RMarkdown notebooks. I misunderstood the question at first but after some thought I realized that I didn’t know if it would work… but I should try it.

I knew that I could run Python chunks in an RMarkdown notebook. And I knew how to change the working conda environment so I could install sympy. But I wasn’t so sure about getting the \(LaTeX\) produced by sympy to print out properly.

I tend to explicitly set my conda environment in my RMD file. Here I set it to r-reticulate which should be the default, but I do this so that it will remind me later what environment I’m using. Because when I come back to this in a few months I’ll have forgotten.

library(reticulate)
use_condaenv(condaenv = "r-reticulate", required=TRUE)

to install conda packages from R or from your Rmd file you can do something like:

reticulate::conda_install("r-reticulate","sympy")

Or you can use conda to activate the environment and install sympy with conda install -c anaconda sympy

The we can do magic like this:

Then we can run some Python chunks that depend on sympy

from sympy import *
x = symbols('x')
a = Integral(cos(x)*exp(x), x)
output = Eq(a, a.doit()) 
print('$' + latex(output) + '$')

\(\int e^{x} \cos{\left(x \right)}\, dx = \frac{e^{x} \sin{\left(x \right)}}{2} + \frac{e^{x} \cos{\left(x \right)}}{2}\)

This works because of two pieces of code. One of which you can’t see above. In the code chunk that runs above I set the language to python and told it to print out the results asis:

{python, results='asis'}

The asis flag tells knitr not to molest the resulting text string, just send it straight to the display. When I did that at first I ended up with this:

from sympy import *
x = symbols('x')
a = Integral(cos(x)*exp(x), x)
output = Eq(a, a.doit()) 
print( latex(output)  )

e^{x} , dx = +

Which baffled me because that’s \(LaTeX\) but it’s not rendered… then (with some google help) I realized that in RMarkdown if we have stand alone \(LaTeX\) we wrap them in dollar signs to tell knitr to render them… in this case using MathJax. So I just added $ around the content like this:

print('$' + latex(output) + '$')

Of course if I were going to do this more than once I’d make a function to do it like this:

from sympy import *
def latex_rmd_print(input_string):
   print('$' + latex(input_string) + '$')

Which then makes the earlier example a lot simpler… but don’t forget the results='asis' in any code chunk that calls latex_rmd_print:

x = symbols('x')
a = Integral( cos(x)*exp(x), x )
latex_rmd_print( Eq(a, a.doit()) )

\(\int e^{x} \cos{\left(x \right)}\, dx = \frac{e^{x} \sin{\left(x \right)}}{2} + \frac{e^{x} \cos{\left(x \right)}}{2}\)

 Share!

 
comments powered by Disqus