使用knitr在Rnw文档中编写SQL代码

5

我在.Rmd文档中使用了以下的sql代码。然而,我想在.Rnw文档中使用相同的SQL代码。

```{r label = setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, max.print = NA)
```

```{r, echo=FALSE, results='hide'}
library(DBI)
db <- dbConnect(RSQLite::SQLite(), dbname = "survey.db")
dbListTables(db)
```


```{sql, label = Q1, connection=db, tab.cap = "Table Caption"}
SELECT * 
  FROM Person;
```

希望能够获得代码格式化和输出打印功能。


不确定您是否已经看到了这个(也不知道它是否有帮助):http://yihui.name/knitr/demo/engines/ - Frank
1
谢谢@Frank提供的链接。我已经看过了,但它并不有用。 - MYaseen208
1
我不确定我是否理解了问题 - 你是在寻找类似于这个的东西吗? - CL.
1
我认为你正在使用Sweave而不是knitr。请检查你的RStudio设置。此外,似乎在RNW文档中没有隐式的LIMIT,所以最好在查询中添加类似于LIMIT 10的内容。一旦这个问题解决了,我们就可以转向如何漂亮地格式化输出的问题... - CL.
我一旦弄清楚如何做到这两点,就会立即开始。;-) - CL.
显示剩余2条评论
1个回答

4
将RMarkdown移植到RNW需要进行一些调整:
  • 当然,需要调整代码块定界符:` ```{r, echo=FALSE}` 的RNW等效写法是 `< >=` ,RNW代码块以 `@` 结尾。(见最小化RNW示例)
  • 重要的是,在RMarkdown文档中,代码块总是指定引擎,而在RNW中,默认为R引擎,除非设置了 `engine` 选项。因此, ` ```{r}` 简化为 `< <>>=` ,但 ` ```{sql}` 的等效写法是 `< >=`。
  • RMarkdown在嵌入SQL块时包括一些非常有用的技巧,请参见knitr语言引擎:在rmarkdown.rstudio.com上使用SQL。默认情况下,结果呈现为漂亮的表格,并且仅打印前10个结果。在RNW中,我们需要自己处理这个问题。

对于在RMarkdown中嵌入SQL,请注意必须通过 `connection` 选项将SQL连接传递给SQL块。选项 `output.var` 可用于指定将查询结果分配给的对象的名称。

一个简单的解决方案(请参见以前的版本)是将SQL结果分配给一个对象,例如 `res`,使用 `output.var`,并添加另一个R块,漂亮地打印 `res`,例如使用 `xtable`。但是,还有一种更优雅的方法,即使用hooks

该示例使用sqlitetutorial.netSQLite示例数据库。在运行代码之前,请将其解压缩到您的工作目录中。

\documentclass{article}

\begin{document}
\thispagestyle{empty}
<<include=FALSE>>=
library(knitr)
library(DBI)

knit_hooks$set(formatSQL = function(before, options, envir) {
  if (!before && opts_current$get("engine") == "sql") {
    sqlData <- get(x = opts_current$get("output.var"))
    max.print <- min(nrow(sqlData), opts_current$get("max.print"))
    myxtable <- do.call(xtable::xtable, c(list(x = sqlData[1:max.print, ]), opts_current$get("xtable.args")))
    capture.output(myoutput <-do.call(xtable::print.xtable, c(list(x = myxtable, file = "test.txt"), opts_current$get("print.xtable.args"))))
    return(asis_output(paste(
      "\\end{kframe}", 
      myoutput,
      "\\begin{kframe}")))
  }
})

opts_chunk$set(formatSQL = TRUE)
opts_chunk$set(output.var = "formatSQL_result")
opts_chunk$set(max.print = getOption("max.print"))

@

<<echo=FALSE, results="hide">>=
db <- dbConnect(RSQLite::SQLite(), dbname = "chinook.db")
@

<<engine = "sql", connection=db, max.print = 8, xtable.args=list(caption = "My favorite artists?", label="tab:artist"), print.xtable.args=list(comment=FALSE, caption.placement="top")>>=
SELECT *  FROM artists;
@

\end{document}

新增了一个块钩子formatSQL。(当相应的块选项不为NULL时,块钩子会运行。)在使用engine="sql"的块后,它将 SQL 结果读入sqlData中。然后,它使用xtable打印结果的前max.print行。
默认情况下,激活块钩子formatSQL(即全局设置为TRUE),并将 SQL 结果存储在formatSQL_result中。块选项max.print控制要打印的行数(将其设置为Inf以始终打印所有行)。 xtable生成的表高度可定制。块选项xtable.args传递给xtableprint.xtable.args传递给print.xtable。在示例中,这些选项用于设置标题、标签,并禁止xtable的默认注释。
以下是生成的PDF。请注意,在RNW中对非 R 代码进行语法突出显示需要安装highlight并将目录添加到路径中(Windows)。

Output


很棒@CL,运行得很好。如果您能指导如何将标题放在表格顶部,将不胜感激。非常感谢您的帮助。 - MYaseen208
1
@MYaseen208 只需将 caption.placement="top" 传递给 print.xtable - CL.
感谢@CL.的帮助。还有两件事需要修改,knitr中的knitr2pdf命令会在控制台上显示不必要的xtable输出。另外,想知道如何全局使用caption.placement="top"connection=db,而不是局部使用。有什么想法吗? - MYaseen208
1)控制台中的xtable输出:请参见编辑。2)参见?print.xtable:全局选项xtable.caption.placement。3)全局变量connection=db:不认为这是可能的。 - CL.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接