使用钩子格式化输出中的表格

时间:2023-01-14 10:36:47

Using knitr and R Markdown, I can produce a tabularised output from a matrix using the following command:

使用knitr和R Markdown,我可以使用以下命令从矩阵生成表格化输出:

```{r results='asis'}
kable(head(x))
```

However, I’m searching for a way to make the kable code implicit since I don’t want to clutter the echoed code with it. Essentially, I want this:

但是,我正在寻找一种隐藏kable代码的方法,因为我不想用它来混淆回显的代码。基本上,我想要这个:

```{r table=TRUE}
head(x)
```

… to yield a formatted tabular (rather than the normal output='markdown') output.

...产生格式化的表格(而不是正常的输出='降价')输出。

I actually thought this must be pretty straightforward since it’s a pretty obvious requirement, but I cannot find any way to achieve this, either via the documentation or on the web.

我实际上认为这必须非常简单,因为这是一个非常明显的要求,但我无法通过文档或网络找到任何方法来实现这一点。

My approach to create an output hook fails because once the data arrives at the hook, it’s already formatted and no longer the raw data. Even when specifying results='asis', the hook obtains the output as a character string and not as a matrix. Here’s what I’ve tried:

我创建输出挂钩的方法失败,因为一旦数据到达挂钩,它就已经格式化,不再是原始数据。即使指定results ='asis',钩子也会将输出作为字符串而不是矩阵获得。这是我尝试过的:

default_output_hook <- knit_hooks$get('output')
knit_hooks$set(output = function (x, options)
    if (! is.null(options$table))
        kable(x)
    else
        default_output_hook(x, options)
)

But like I said, this fails since x is not the original matrix but rather a character string, and it doesn’t matter which value for the results option I specify.

但就像我说的那样,这失败了,因为x不是原始矩阵而是字符串,并且我指定的结果选项的哪个值无关紧要。

2 个解决方案

#1


1  

Lacking a better solution I’m currently re-parsing the character string representation that I receive in the hook. I’m posting it here since it kind of works. However, parsing a data frame’s string representation is never perfect. I haven’t tried the following with anything but my own data and I fully expect it to break on some common use-cases.

缺乏更好的解决方案我正在重新解析我在钩子中收到的字符串表示。我在这里发布,因为它有点工作。但是,解析数据框的字符串表示永远不是完美的。除了我自己的数据之外,我没有尝试过以下任何内容,我完全希望它可以打破一些常见的用例。

reparse <- function (data, comment, ...) {
    # Remove leading comments
    data <- gsub(sprintf('(^|\n)%s ', comment), '\\1', data)
    # Read into data frame
    read.table(text = data, header = TRUE, ...)
}

default_output_hook <- knit_hooks$get('output')

knit_hooks$set(output = function (x, options)
    if (is.null(options$table))
        default_output_hook(x, options)
    else {
        extra_opts <- if (is.list(options$table)) options$table else list()
        paste(kable(do.call(reparse, c(x, options$comment, extra_opts))),
              collapse = '\n')
    }
)

This will break if the R markdown comment option is set to a character sequence containing a regular expression special char (e.g. *), because R doesn’t seem to have an obvious means of escaping a regular expression.

如果R markdown注释选项设置为包含正则表达式特殊字符(例如*)的字符序列,则会中断,因为R似乎没有明显的方法来转义正则表达式。

Here’s a usage example:

这是一个用法示例:

```{r table=TRUE}
data.frame(A=1:3, B=4:6)
```

You can pass extra arguments to the deparse function. This is necessary e.g. when the table contains NA values because read.table by default interprets them as strings:

您可以将额外的参数传递给deparse函数。这是必要的,例如当表包含NA值时,因为read.table默认将它们解释为字符串:

```{r table=list(colClasses=c('numeric', 'numeric'))}
data.frame(A=c(1, 2, NA, 3), B=c(4:6, NA))
```

Far from perfect, but at least it works (for many cases).

远非完美,但至少它起作用(对许多情况而言)。

#2


1  

Not exactly what you are looking for, but I am posting an answer here (that could not fit in a comment) as your described workflow is really similar to what my initial goal and use-case was when I started to work on my pander package. Although I really like the bunch of chunk options that are available in knitr, I wanted to have an engine that makes creating documents really easy, automatic and without any needed tweaks. I am aware of the fact that knitr hooks are really powerful, but I just wanted to set a few things in my Rprofile and let the literate programming tool its job without further trouble, that ended to be Pandoc.brew for me.

不完全是你想要的,但我在这里发布一个答案(这不符合评论),因为你描述的工作流程与我最初的目标和用例在我开始使用我的pander包时非常相似。虽然我非常喜欢knitr中提供的一系列块选项,但我希望有一个引擎可以让创建文档变得非常简单,自动且不需要任何调整。我知道knitr钩子真的很强大,但我只是想在我的Rprofile中设置一些东西,让文字编程工具没有进一步的麻烦,最终成为Pandoc.brew。

The main idea is to specify a few options (what markdown flavour are you using, what's your decimal mark, favorite colors for your charts etc), then simply write your report in a brew syntax without any chunk options, and the results of your code would be automatically transformed to markdown. Then convert that to pdf/docx/odt etc. with Pandoc.

主要的想法是指定一些选项(你使用什么markdown风格,你的十进制标记是什么,你的图表最喜欢的颜色等),然后简单地用brew语法编写你的报告,没有任何块选项,以及代码的结果将自动转换为降价。然后用Pandoc将其转换为pdf / docx / odt等。

#1


1  

Lacking a better solution I’m currently re-parsing the character string representation that I receive in the hook. I’m posting it here since it kind of works. However, parsing a data frame’s string representation is never perfect. I haven’t tried the following with anything but my own data and I fully expect it to break on some common use-cases.

缺乏更好的解决方案我正在重新解析我在钩子中收到的字符串表示。我在这里发布,因为它有点工作。但是,解析数据框的字符串表示永远不是完美的。除了我自己的数据之外,我没有尝试过以下任何内容,我完全希望它可以打破一些常见的用例。

reparse <- function (data, comment, ...) {
    # Remove leading comments
    data <- gsub(sprintf('(^|\n)%s ', comment), '\\1', data)
    # Read into data frame
    read.table(text = data, header = TRUE, ...)
}

default_output_hook <- knit_hooks$get('output')

knit_hooks$set(output = function (x, options)
    if (is.null(options$table))
        default_output_hook(x, options)
    else {
        extra_opts <- if (is.list(options$table)) options$table else list()
        paste(kable(do.call(reparse, c(x, options$comment, extra_opts))),
              collapse = '\n')
    }
)

This will break if the R markdown comment option is set to a character sequence containing a regular expression special char (e.g. *), because R doesn’t seem to have an obvious means of escaping a regular expression.

如果R markdown注释选项设置为包含正则表达式特殊字符(例如*)的字符序列,则会中断,因为R似乎没有明显的方法来转义正则表达式。

Here’s a usage example:

这是一个用法示例:

```{r table=TRUE}
data.frame(A=1:3, B=4:6)
```

You can pass extra arguments to the deparse function. This is necessary e.g. when the table contains NA values because read.table by default interprets them as strings:

您可以将额外的参数传递给deparse函数。这是必要的,例如当表包含NA值时,因为read.table默认将它们解释为字符串:

```{r table=list(colClasses=c('numeric', 'numeric'))}
data.frame(A=c(1, 2, NA, 3), B=c(4:6, NA))
```

Far from perfect, but at least it works (for many cases).

远非完美,但至少它起作用(对许多情况而言)。

#2


1  

Not exactly what you are looking for, but I am posting an answer here (that could not fit in a comment) as your described workflow is really similar to what my initial goal and use-case was when I started to work on my pander package. Although I really like the bunch of chunk options that are available in knitr, I wanted to have an engine that makes creating documents really easy, automatic and without any needed tweaks. I am aware of the fact that knitr hooks are really powerful, but I just wanted to set a few things in my Rprofile and let the literate programming tool its job without further trouble, that ended to be Pandoc.brew for me.

不完全是你想要的,但我在这里发布一个答案(这不符合评论),因为你描述的工作流程与我最初的目标和用例在我开始使用我的pander包时非常相似。虽然我非常喜欢knitr中提供的一系列块选项,但我希望有一个引擎可以让创建文档变得非常简单,自动且不需要任何调整。我知道knitr钩子真的很强大,但我只是想在我的Rprofile中设置一些东西,让文字编程工具没有进一步的麻烦,最终成为Pandoc.brew。

The main idea is to specify a few options (what markdown flavour are you using, what's your decimal mark, favorite colors for your charts etc), then simply write your report in a brew syntax without any chunk options, and the results of your code would be automatically transformed to markdown. Then convert that to pdf/docx/odt etc. with Pandoc.

主要的想法是指定一些选项(你使用什么markdown风格,你的十进制标记是什么,你的图表最喜欢的颜色等),然后简单地用brew语法编写你的报告,没有任何块选项,以及代码的结果将自动转换为降价。然后用Pandoc将其转换为pdf / docx / odt等。