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

  • 从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)
    ```
    

    您对这些奇怪的行为以及如何规避这些行为有解释吗?

    最佳答案

    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/

    10-12 16:33