10

I am using conTeXt to create pdfs (I need to use Context rather than any other latex engine because I am using their tagging feature to create pdfs with tagged document trees).

I would like to be able to use R code to calculate some numbers that would then be displayed in my document (like you could do latex and Sweave). Is there any way to do this?

1 Answer 1

9

In short, yes, using the filter module. In fact, the filter module has a specific example for using R. I'm not sure about Sweave, but the integration doesn't seem to be quite as tight as something like knitr (although I'm no filter expert either). The author of the module, Aditya, is quite active on this site so he will likely chime in with his answer. In the meantime though, you can take a look at the setup I use.

Update:

I added JSON output from R and input into Lua (from context) to allow recalling arbitrary values from R directly into the context code. The approach can probably be fine-tuned, but the idea is as follows:

  1. In R chunks, store objects you want to use into a JSON file (I used jsonlite package)
  2. In context, use \startluacode, \stopluacode block to load the JSON file into a lua table (I used the json.lua module by literally copy and pasting the json.lua file into my document directory)
  3. Then use \ctxlua{} combined with the context() command from ctxlua to actually load data from the lua table and into the document.

And the overall code

% Note that the following assumes the existence of "vimcode" and "Rcode"
% directories, which you can change with the directory option.
% You will also need to download the lua.json file.

%------------------------------------------------------------------------
% Optional setup using vimtyping for R syntax
\usemodule[vim]

\definevimtyping
  [Rcode]
  [syntax=r,
   directory=vimcode/,
   tab=2,
   margin=2em,
   strip=yes,
   before={\blank[big]},
   style=mono]

%------------------------------------------------------------------------
% Issuing R commands from context
\usemodule[filter]

% Helper buffers to keep an ongoing session using the session library
\startbuffer[Rstart]
  library(session)
  if (file.exists("Rcode/session.Rsession")) {
    restore.session(file="Rcode/session.Rsession")
  }
\stopbuffer

\startbuffer[Rstop]
  save.session(file="Rcode/session.Rsession")
\stopbuffer

% The actual R filter definition
\defineexternalfilter[R][
  filtercommand={R CMD BATCH --quiet --vanilla 
                 \externalfilterinputfile\space \externalfilteroutputfile},
  output=\externalfilterbasefile.out,
  bufferbefore={Rstart},
  bufferafter={Rstop},
  readcommand=\typefile,
  directory=Rcode,
  read=no,
  cache=yes]

%------------------------------------------------------------------------
% Setting up csv file processing
\usemodule[database]

\defineseparatedlist[CSVNatural]
  [separator={,},
   quotechar={"},
   before=\bTABLE,
   after=\eTABLE,
   first=\bTR,
   last=\eTR,
   left=\bTD,
   right=\eTD]

\defineseparatedlist[CSV]
  [separator={,},
   quotechar={"},
   before=\starttabulate,
   after=\stoptabulate,
   first=\NC,
   last=\NR,
   left=,
   right=\NC]

%------------------------------------------------------------------------
% Lua code for reading JSON files
\startluacode

  json = require "json"

  function file_exists(file)
    local f = io.open(file, "rb")
    if f then f:close() end
    return f ~= nil
  end

  function read_string(file)
    if not file_exists(file) then return '' end
    out = ''
    for line in io.lines(file) do 
      out = out .. line
    end
    return out
  end

  function read_json(file)
    out = json.decode(read_string(file))
    return out
  end

\stopluacode


\starttext

An example of using inline R syntax: \inlineRcode{m <- lm(y ~ x, data = d)}

And another example using a syntax block:

\startRcode
d <- data.frame(x = rnorm(5), y = rnorm(5))
m <- lm(y ~ x, data = d)
\stopRcode

I use the database module for generating tables and then loading them:

\startR
d <- data.frame(x = rnorm(5), y = rnorm(5))
write.csv(d, './Rcode/test.csv')
m <- lm(y ~ x, data = d)

# Output results to JSON
library(jsonlite)
export = toJSON(list(coeff = m$coeff))
write(export, file='./Rcode/export.JSON')
\stopR

\processdatabasefile[CSVNatural][Rcode/test.csv]

To use the JSON data you exported in the last block, import it into lua:

\startluacode
Rdata = read_json('./Rcode/export.JSON')
\stopluacode

And you can access R data using ctxlua, so slope should be: \ctxlua{context(Rdata.coeff[1])}

And plots are included as normal:

\startR
# Note that the session package makes sure d persists from last block
pdf('./Rcode/test.pdf', width = 5, height = 5)
plot(d$x, d$y)
dev.off()
\stopR

\externalfigure[Rcode/test.pdf] 

\stoptext

This is what the output looks like on my computer:

pdf output

9
  • This is an incredibly helpful and detailed answer! Thank you so much! Oct 5, 2018 at 14:56
  • @clairekelley Happy to help! I noticed that you posted a similar question on the mailing list. If you need more help, it might be useful if you mention a specific feature that you are missing. One thing that I didn't answer is how to pull out a specific value from R and use it in the text. I'm not actually sure how that would work, but it's not something I personally use.
    – ssokolen
    Oct 5, 2018 at 15:53
  • @ssokolen- the main thing i need it to be able to pull a specific value out of R- so I am hoping that someone in the mailing list will have a suggestion! Oct 5, 2018 at 16:02
  • 1
    Rscript fits my needs stackoverflow.com/a/14433478/2755116 \defineexternalfilter [R] [filtercommand={Rscript \externalfilterinputfile\space > \externalfilteroutputfile}, output=\externalfilterbasefile.out, cache=yes] just prints out output Jul 11, 2021 at 15:23
  • 1
    @somenxavier Glad that you found an alternative. Rscript does make a little bit more sense. I just tend to use the cat command when printing stuff out and assign everything to variables otherwise.
    – ssokolen
    Jul 15, 2021 at 20:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .