<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/generating-text-from-an-r-dataframe-using-pytracery-pandas-and-reticulate/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://blog.ouseful.info/2018/04/08/generating-text-from-r-dataframe-using-pytracery-and-reticulate/"> Rstats – OUseful.Info, the blog…</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>In a couple of recent posts (<a rel="nofollow" href="https://blog.ouseful.info/2018/02/11/to-do-textualisation-with-tracery-and-database-reporting-2-0/" target="_blank">Textualisation With Tracery and Database Reporting 2.0</a> and <a rel="nofollow" href="https://blog.ouseful.info/2018/03/11/more-tinkering-with-pytracery/" target="_blank">More Tinkering With PyTracery</a>) I’ve started exploring various ways of using the <code>pytracery</code> port of the <a rel="nofollow" href="http://tracery.io/" target="_blank">tracery</a> story generation tool to generate variety of texts from Python <em>pandas</em> data frames.</p>
<p>For my F1DataJunkie tinkerings I’ve been using R + SQL as the base languages, with some hardcoded Rdata2text constructions for rendering text from R dataframes (<a rel="nofollow" href="https://blog.ouseful.info/2018/04/07/sketch-data-trivia/" target="_blank">example</a>).</p>
<p>Whilst there is a basic port of tracery to R, I want to make use of the various extensions I’ve been doodling with to <code>pytracery</code>, so it seemed like a good opportunity to start exploring the R <code>reticulate</code> package.</p>
<p>It was a bit of a faff trying to get things to work the first time, so here on some notes on what I had to consider to get a trivial demo working in my RStudio/Rmd/knitr environment.</p>
<h3>Python Environment</h3>
<p>My first attempt was to use <em>python</em> blocks in an Rmd document:</p>
<pre>```{python}
import sys
print(sys.executable)
````</pre>
<p>but R insisted on using the base Python path on my Mac that <em>was not</em> the path I wanted to use… The fix turned out to be setting the engine…</p>
<pre>```{python, engine.path ='/Users/f1dj/anaconda3/bin/python' }
import sys
print(sys.executable)
````</pre>
<p>This could also be done via a setting: <code>opts_chunk$set(engine.path = '/Users/f1dj/anaconda3/bin/python')</code></p>
<p>One of the problems with this approach is that a Python environment is created for each chunk – so you can’t easily carry state over from one Python chunk to another.</p>
<p>So I had a look at a workaround using <code>reticulate</code> instead.</p>
<h3>Calling <code>pytracery</code> from R using <code>reticulate</code></h3>
<p>The solution I think I’m going for is to put Python code into a file, call that into R, then pass an R dataframe as an argument to a called Python function and gett a response back into R as an R dataframe.</p>
<p>For example, here’s a simple <em>python</em> test file:</p>
<pre>import tracery
from tracery.modifiers import base_english
import pandas as pd

def pandas_row_mapper(row, rules, root,  modifiers=base_english):
    ''' Function to parse single row of dataframe '''
    row=row.to_dict()
    rules=rules.copy()

    for k in row:
        rules[k] = str(row[k])
        grammar = tracery.Grammar(rules)
        if modifiers is not None:
            if isinstance(modifiers,list):
                for modifier in modifiers:
                    grammar.add_modifiers(modifier)
            else:
                grammar.add_modifiers(modifiers)

    return grammar.flatten(root)

def pandas_tracery(df, rules, root, modifiers=base_english):
  return df.apply(lambda row: pandas_row_mapper(row, rules, root, modifiers), axis=1)

def pdt_inspect(df):
  return(df)

def pdt_test1(df):
  return type(df)

def pdt_demo(df):
  return pandas_tracery(df, _demo_rules, &quot;#origin#&quot;,  modifiers=base_english)

#Create example rule to apply to each row of dataframe
_demo_rules = {'origin': &quot;#code# was placed #position#!&quot;,
         'position': &quot;#pos.uppercase#&quot;}
</pre>
<p>We can access a python environment using <code>reticulate</code>:</p>
<pre>library(reticulate)

#Show conda environments
conda_list(&quot;auto&quot;)

#Use a particular, name conda environment
use_condaenv(condaenv='anaconda3', required=T)

#Check the availability of a particular module in the environment
py_module_available(&quot;tracery&quot;)</pre>
<p>Now we can load in the python file – and the functions it defines – and then call one of the  loaded Python functions.</p>
<p>Note that I seemed to have to force the casting of the R dataframe to a python/pandas dataframe using <code>r_to_py()</code>, although I’d expected the type mapping to be handled automatically? (Perhaps there is a setting somewhere?)</p>
<pre>
```{r}
source_python(&quot;pd_tracery_demo.py&quot;)
df1=data.frame(code=c('Jo','Sam'), pos=c('first','Second'))
df1$result = pdt_demo(r_to_py(df1, convert=T))
df1
```

#Displays:
Jo	first	Jo was placed FIRST!
Sam	Second	Sam was placed SECOND!
</pre>
<p>(Note: I also spotted a gotcha – things don’t work so well if you define an R column name called <code>name</code>… )</p>
<p>So now I can start looking at converting sports reporting tropes like these:</p>
<p><img data-orig-file="https://ouseful.files.wordpress.com/2018/04/27442068108_269e63e420_k.jpg?w=450&amp;h=873&amp;fit=491%2C873" data-orig-size="1152,2048" data-medium-file="https://ouseful.files.wordpress.com/2018/04/27442068108_269e63e420_k.jpg?w=450&amp;h=873&amp;fit=491%2C873?w=169" data-attachment-id="17730" data-image-meta="{" data-image-description="" src="https://ouseful.files.wordpress.com/2018/04/27442068108_269e63e420_k.jpg?w=450&h=873&fit=491%2C873" data-permalink="https://blog.ouseful.info/2018/04/08/generating-text-from-r-dataframe-using-pytracery-and-reticulate/27442068108_269e63e420_k/" data-large-file="https://ouseful.files.wordpress.com/2018/04/27442068108_269e63e420_k.jpg?w=450&amp;h=873&amp;fit=491%2C873?w=576" alt="" data-image-title="27442068108_269e63e420_k" sizes="(max-width: 491px) 100vw, 491px" data-comments-opened="1" class="wp-image-17730" data-recalc-dims="1"></p>
<p>into <em>tracery</em> story models I can call using my <em>pandas</em>/<em>pytracery</em> hacks:-)</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://blog.ouseful.info/2018/04/08/generating-text-from-r-dataframe-using-pytracery-and-reticulate/"> Rstats – OUseful.Info, the blog…</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/S6rycex1Lc4" height="1"></a></div>