我正在使用 conTeXt 来创建 pdf(我需要使用 Context 而不是任何其他 latex 引擎,因为我正在使用它们的标记功能来创建带有标记文档树的 pdf)。
我希望能够使用 R 代码来计算一些数字,然后将其显示在我的文档中(就像您可以使用 latex 和 Sweave 一样)。有什么办法吗?
答案1
简而言之,是的,使用过滤模块。事实上,过滤模块有一个使用 R 的具体示例。我不确定 Sweave 是否如此,但它的集成度似乎不如 knitr 那样高(尽管我也不是过滤器专家)。该模块的作者 Aditya 在这个网站上非常活跃,所以他很可能会给出答案。不过,在此期间,您可以查看我使用的设置。
更新:
我添加了 R 的 JSON 输出和 Lua 的输入(来自上下文),以便允许将 R 中的任意值直接调用到上下文代码中。该方法可能需要微调,但思路如下:
- 在 R 块中,将要使用的对象存储到 JSON 文件中(我使用了 jsonlite 包)
- 在上下文中,使用
\startluacode
,\stopluacode
块将 JSON 文件加载到 lua 表中(我使用了json.lua模块,通过将 json.lua 文件复制并粘贴到我的文档目录中) - 然后
\ctxlua{}
结合context()
命令使用,ctxlua
将数据从 lua 表实际加载到文档中。
总体代码
% 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
这是在我的电脑上输出的内容: