我试图了解使用knitr软件包(在Ubuntu 14.04上的RStudio 0.98.977中)编织HTML时,kable函数的以下两个意外行为:
下面是一个示例代码:
Load library:
```{r init}
library("knitr")
```
Define dataframe:
```{r define_dataframe}
df <- data.frame(letters=c("a", "b", "c"), numbers=c(1, 2, 3))
rownames(df) <- c("x", "y", "z")
```
### Example 1: pretty display with simple call
The dataframe is displayed nicely twice when knitting HTML with the following code:
```{r pretty_display1, results="asis"}
kable(df)
kable(df)
```
### Example 2: unexpected display with lapply
The dataframe is displayed nicely only the first time when knitting HTML with the following code:
```{r unexpected_display1, results="asis"}
lst <- list(df, df)
lapply(lst, kable)
```
### Example 3: pretty display with function
The dataframe is displayed nicely twice when knitting HTML with the following code:
```{r pretty_display2, results="asis"}
foo1 <- function (df) {
kable(df)
}
foo2 <- function (df) {
foo1(df)
foo1(df)
}
foo2(df)
```
### Example 4: unexpected display with function containing print statements
The dataframe is displayed nicely only the second time when knitting HTML with the following code:
```{r unexpected_display2, results="asis"}
foo1 <- function (df) {
kable(df)
}
foo2 <- function (df) {
print("first display")
foo1(df)
print("second display")
foo1(df)
}
foo2(df)
```
您对这些奇怪的行为以及如何规避这些行为有解释吗?
最佳答案
kable
的输出是副作用。您可以将输出的值存储在变量中,但是仅运行kable
就会将某些内容输出到控制台。当您两次运行kable(df)
时,这不是问题,您什么也不存储,该函数将输出两次转储到控制台。
但是,当您运行lapply(lst, kable)
时,该函数将输出转储到控制台,然后显示列表的值。尝试仅在控制台中运行此命令:
lst <- list(df, df)
lapply(lst, kable)
您应该得到以下确切信息:
| |letters | numbers|
|:--|:-------|-------:|
|x |a | 1|
|y |b | 2|
|z |c | 3|
| |letters | numbers|
|:--|:-------|-------:|
|x |a | 1|
|y |b | 2|
|z |c | 3|
[[1]]
[1] "| |letters | numbers|" "|:--|:-------|-------:|"
[3] "|x |a | 1|" "|y |b | 2|"
[5] "|z |c | 3|"
[[2]]
[1] "| |letters | numbers|" "|:--|:-------|-------:|"
[3] "|x |a | 1|" "|y |b | 2|"
[5] "|z |c | 3|"
注意如何输出正确的markdown,然后显示您创建的列表的实际值。这就是造成不良输出的原因。
功能范例在副作用方面效果不佳,因此有两种选择。您可以通过将
kable
参数设置为output
来存储FALSE
的结果,或者仅使用for
来浏览list
,否则可以阻止结果列表的显示。这是一些可行的例子。```{r nograpes1, results="asis"}
lst <- list(df, df)
for(x in lst) kable(x) # Don't create a list, just run the function over each element
```
```{r nograpes2, results="asis"}
lst <- list(df, df)
invisible(lapply(lst, kable)) # prevent the displaying of the result list.
```
```{r nograpes3, results="asis"}
lst <- list(df, df)
l <- lapply(lst, kable) # Store the list and do nothing with it.
```
在我看来,这是在R中应使用
for
的一个很好的示例,因为它最清楚地表达了您希望如何使用基于副作用的函数。关于r - 从lapply或带print语句的函数中调用kable时,其行为异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25344067/