从lapply或带print语句的函数中调用kable时,其行为异常 [英] Unexpected behavior of kable when called from lapply or from function with print statement
问题描述
在尝试使用knitr软件包编织HTML时(在Ubuntu 14.04上的RStudio 0.98.977中),我试图了解kable函数的以下两个意外行为:
I am trying to understand the two following unexpected behaviors of the kable function when knitting HTML using the knitr package (in RStudio 0.98.977 on Ubuntu 14.04):
- 从lapply内两次调用kable时,只有第一个调用会在最终的HTML中产生漂亮的显示.
- 当在同样使用print语句的函数中进行两次kable调用时,只有最后一次调用会在最终HTML中产生漂亮的显示.
下面是一个示例代码:
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)
```
您对这些奇怪的行为有何解释,以及如何规避它们?
Do you have an explanation to these strange behaviors and how to circumvent them?
推荐答案
kable
的输出是副作用.您可以将输出的值存储在变量中,但是仅运行kable
就会将某些内容输出到控制台.两次运行kable(df)
时,这不是问题,您什么也不存储,该函数两次将输出转储到控制台.
The output of kable
is a side-effect; you can store the value of the output in a variable, but just running kable
will output something to console. When you run kable(df)
twice, this isn't a problem, you aren't storing anything, and the function dumps the output to the console twice.
但是,当您运行lapply(lst, kable)
时,该函数将输出转储到控制台,然后显示列表的值.尝试仅在控制台中运行它:
However, when you run lapply(lst, kable)
, the function dumps the output to the console and then the value of the list is displayed. Try running this just in your console:
lst <- list(df, df)
lapply(lst, kable)
您应该完全明白这一点:
You should get exactly this:
| |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|"
注意如何输出正确的减价,然后显示您创建的列表的实际值.这就是造成不良输出的原因.
Notice how the correct markdown is output, and then the actual value of the list you created is displayed. This is what creates the bad output.
功能范式在副作用方面效果不佳,因此有两种选择.您可以通过将output
参数设置为FALSE
来存储kable
的结果,或者可以仅使用for
浏览list
,或者可以防止显示结果列表.这是一些可行的示例.
The functional paradigm doesn't work particularly well with side-effects, so you have a couple of options. You can store the results of kable
by setting the output
parameter to FALSE
, or you can just use a for
to go through your list
, or you could prevent the displaying of the result list. here are some examples that will work.
```{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
的一个很好的例子,因为它最清楚地表达了您要如何使用基于副作用的函数.
In my opinion, this is a nice example of when for
should be used in R, as it most cleanly expresses how you want to use a side-effect based function.
这篇关于从lapply或带print语句的函数中调用kable时,其行为异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!