从lappy或从带有print语句的函数调用时,kable的意外行为

从lappy或从带有print语句的函数调用时,kable的意外行为,r,knitr,rstudio,lapply,R,Knitr,Rstudio,Lapply,我试图理解使用knitr包编织HTML时kable函数的以下两个意外行为(在Ubuntu 14.04上的RStudio 0.98.977中): 当从lappy中调用两个kable时,只有第一个调用在最终的HTML中生成一个漂亮的显示 当在一个也使用print语句的函数中进行两次kable调用时,只有最后一次调用在最终的HTML中生成一个漂亮的显示 下面编写了一个示例代码: Load library: ```{r init} library("knitr") ``` Define datafr

我试图理解使用knitr包编织HTML时kable函数的以下两个意外行为(在Ubuntu 14.04上的RStudio 0.98.977中):

  • 当从lappy中调用两个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)
    ```
    
    加载库:
    ```{r init}
    图书馆(“knitr”)
    ```
    定义数据帧:
    ```{r define_dataframe}
    
    dfkable的输出是副作用;您可以将输出值存储在变量中,但只需运行
    kable
    即可将某些内容输出到控制台。当您运行两次
    kable(df)
    时,这不是问题,您没有存储任何内容,并且函数将输出转储到控制台两次

    但是,当您运行
    lappy(lst,kable)
    时,该函数将输出转储到控制台,然后显示列表的值。请尝试在控制台中运行此命令:

    lst <- list(df, df)
    lapply(lst, kable)
    
    请注意如何输出正确的标记,然后显示您创建的列表的实际值。这就是造成不良输出的原因

    功能范式对副作用的作用不是特别好,所以你有两种选择。通过将
    output
    参数设置为
    FALSE
    ,您可以存储
    kable
    的结果,或者您可以使用
    for
    来浏览
    列表
    ,或者您可以阻止显示结果列表。下面是一些有用的例子

    ```{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=1,results=“asis”}
    
    lstnograps为您关于
    lappy
    的问题提供了一个很好的答案。在这里,我试图回答你问题的另一部分

    print
    函数的副作用是将字符串打印到输出中。第一个
    print
    函数在
    kable
    调用后立即调用,该调用在RMarkdown表语法后追加一行。由于RMarkdown语法要求在表格前后都有换行符,因此
    print
    函数会污染
    kable
    输出。因此,第一个
    kable
    输出未正确解析到表中

    如果从区块中删除
    results=“asis”
    部分,可以打印原始RMarkdown输出,以便查看打印:

    ## [1] "first display"
    ## 
    ## 
    ## |   |letters | numbers|
    ## |:--|:-------|-------:|
    ## |x  |a       |       1|
    ## |y  |b       |       2|
    ## |z  |c       |       3|
    ## [1] "second display"  # <- here is the culprit! 
    ## 
    ## 
    ## |   |letters | numbers|
    ## |:--|:-------|-------:|
    ## |x  |a       |       1|
    ## |y  |b       |       2|
    ## |z  |c       |       3|
    

    @nog油菜:)。你在第一部分也打败了我。谢谢你们两位的详细回答!谢谢你的回答!这很有道理。然而,在
    lappy(lst,kable)
    情况下(应该避免,因为您提供了很好的替代方案),我仍然对控制台和HTML显示之间的差异感到困惑。在控制台中,通过副作用打印的两张表是相同的。在HTML输出中,仅正确显示通过副作用生成的第一个表。你知道为什么会发生这种情况吗?@sebastien_vigneau这是因为
    lappy
    (这是一个列表)的返回值被转换成字符串,并立即附加到第二个
    kable
    调用的输出中,造成与您在
    print
    调用中遇到的问题相同的问题。@XinYin现在一切都有意义:)再次感谢您!当您将
    kable
    放入
    for
    循环中时,您不应该按照
    kable
    帮助的建议使用
    print(kable(…)
    ?否则就没有任何输出。
    ## [1] "first display"
    ## 
    ## 
    ## |   |letters | numbers|
    ## |:--|:-------|-------:|
    ## |x  |a       |       1|
    ## |y  |b       |       2|
    ## |z  |c       |       3|
    ## [1] "second display"  # <- here is the culprit! 
    ## 
    ## 
    ## |   |letters | numbers|
    ## |:--|:-------|-------:|
    ## |x  |a       |       1|
    ## |y  |b       |       2|
    ## |z  |c       |       3|
    
    ```{r unexpected_display2, results="asis"}
    foo1 <- function (df) {
      kable(df)
    }
    foo2 <- function (df) {
      cat("\n\nfirst display")
      foo1(df)
      cat("\n\nsecond display")
      foo1(df)
    }
    foo2(df)
    ```