knitr:带有output.lines =选项的输出钩子,其作用类似于echo = 2:6

use*_*089 12 hook r knitr

在一个书籍项目中,我有很多输出我想缩写,只选择一行的子集,并添加...以指示某些输出已被省略.例如,在输出中summary(lm()),我可能只想打印系数表,并使其显示如下:

 >summary(lm(Sepal.Length ~ Species, data=iris))
...
Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)         5.0060     0.0728  68.762  < 2e-16 ***
Speciesversicolor   0.9300     0.1030   9.033 8.77e-16 ***
Speciesvirginica    1.5820     0.1030  15.366  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
...
Run Code Online (Sandbox Code Playgroud)

我编写了以下输出钩子,它使用块选项,output.lines=并接受一个数字,n,意味着只打印行1:n,有点像head():

  # get the default output hook
  hook_output <- knit_hooks$get("output")

  knit_hooks$set(output = function(x, options) {
    lines <- options$output.lines
    if (is.null(lines)) {
      hook_output(x, options)  # pass to default hook
    }
    else {
      x <- unlist(stringr::str_split(x, "\n"))
      if (length(x) > lines) {
        # truncate the output, but add ....
        x <- c(head(x, lines), "...\n")
      }
      # paste these lines together
      x <- paste(x, collapse = "\n")
      hook_output(x, options)
    }
  })
Run Code Online (Sandbox Code Playgroud)

我试图将其概括为接受一个(连续的)行号向量,如下所示,但它似乎不起作用,我不知道为什么.它也不像我想的那样通用,因为传递output.lines=1:12应该只打印1:12行......并且像选项一样echo=,用它output.lines = -1:3...跟随所有剩余的行会很好.

  # knitr hook function to allow an output.lines option
  # e.g., 
  #   output.lines=12 prints lines 1:12 ...
  #   output.lines=3:15 prints lines ... 3:15 ...

   knit_hooks$set(output = function(x, options) {
     lines <- options$output.lines
     if (is.null(lines)) {
       hook_output(x, options)  # pass to default hook
     }
     else {
       x <- unlist(stringr::str_split(x, "\n"))
       more <- "...\n"
       if (length(lines)==1) {        # first n lines
         if (length(x) > lines) {
           # truncate the output, but add ....
           x <- c(head(x, lines), more)
         }
       }
       else {
         x <- c(more, x[lines], more)
      }
       # paste these lines together
       x <- paste(x, collapse = "\n")
       hook_output(x, options)
     }
   })
Run Code Online (Sandbox Code Playgroud)

我认为这是一个比我更普遍的问题,所以也许这对knitr来说是一个受欢迎的补充.

-Michael

Yih*_*Xie 8

我不明白为什么它不应该工作.他们在上面的评论中指出了一个错误(-1:3应该是-(1:3)),这可能是原因.除此之外,它适用于我:

```{r}
library(knitr)
hook_output <- knit_hooks$get("output")
knit_hooks$set(output = function(x, options) {
   lines <- options$output.lines
   if (is.null(lines)) {
     return(hook_output(x, options))  # pass to default hook
   }
   x <- unlist(strsplit(x, "\n"))
   more <- "..."
   if (length(lines)==1) {        # first n lines
     if (length(x) > lines) {
       # truncate the output, but add ....
       x <- c(head(x, lines), more)
     }
   } else {
     x <- c(more, x[lines], more)
   }
   # paste these lines together
   x <- paste(c(x, ""), collapse = "\n")
   hook_output(x, options)
 })
```

Normal output.

```{r test}
summary(lm(Sepal.Length ~ Species, data=iris))
```

The first 4 lines.

```{r test, output.lines=4}
```

Remove the first 8 lines.

```{r test, output.lines=-(1:8)}
```

From 8 to 15.

```{r test, output.lines=8:15}
```
Run Code Online (Sandbox Code Playgroud)

修改输出挂钩后的结果


use*_*089 5

Thell的评论和Yihui的测试案例让我稍微概括一下,所以它现在正是我想要的.

特别是,output.lines=1:12工作原理与output.lines=12初始相同....类似地,对于output.lines=-(1:8)打印初始的情况,...但如果最后一行包含在范围内则省略它.

这现在满足了我的需求,并且可能对其他人来说足够有用,可以包括作为新的knitr chunk选项.从设计的角度来看,唯一可能改变的是仅提供所需行的范围,例如, output.lines=c(1,8)或者output.lines=-c(1,8),因为它将非常混乱并且可能混淆以允许...非连续行选择中的s.

例如,使用当前函数,output.lines=sample(1:15,10)将起作用,并且实际上对打印数据帧的块执行有用的操作,类似于some(iris)car包中.但是,当我想要的时候,我some()直接使用.此输出挂钩仅用于从打印输出中选择一系列行,这些行来自太长而无法有效地包含在打印文档中的功能,或者当您想要将注意力集中在输出的一部分上并指示某些行具有被省略了.

  # knitr hook function to allow an output.lines option
  # e.g., 
  #   output.lines=12 prints lines 1:12 ...
  #   output.lines=1:12 does the same
  #   output.lines=3:15 prints lines ... 3:15 ...
  #   output.lines=-(1:8) removes lines 1:8 and prints ... 9:n ...
  #   No allowance for anything but a consecutive range of lines

library(knitr)
hook_output <- knit_hooks$get("output")
knit_hooks$set(output = function(x, options) {
   lines <- options$output.lines
   if (is.null(lines)) {
     return(hook_output(x, options))  # pass to default hook
   }
   x <- unlist(strsplit(x, "\n"))
   more <- "..."
   if (length(lines)==1) {        # first n lines
     if (length(x) > lines) {
       # truncate the output, but add ....
       x <- c(head(x, lines), more)
     }
   } else {
     x <- c(if (abs(lines[1])>1) more else NULL, 
            x[lines], 
            if (length(x)>lines[abs(length(lines))]) more else NULL
           )
   }
   # paste these lines together
   x <- paste(c(x, ""), collapse = "\n")
   hook_output(x, options)
 })
Run Code Online (Sandbox Code Playgroud)