【问题标题】:programmatically create headers and evaluate following code chunks in markdown以编程方式创建标头并评估 Markdown 中的以下代码块
【发布时间】:2018-09-19 22:05:26
【问题描述】:

我的问题与SO question 类似,但我不想创建情节,而是想评估代码块。我想知道是否有可能以编程方式生成标题评估代码块遵循各自的标题?我的尝试如下。

我有一个 list 的数据帧,我想为每个 list 元素创建一个标头并评估代码块。下面的例子只是使用nrow()计算每个数据框的行数。

```{r data}
data("iris","airquality","mtcars")
my_list <- list(iris,airquality,mtcars)
names(my_list) <- c("iris","airquality","mtcars")
```

```{r headers, results = 'asis'}
for (i in seq_along(my_list)) {
  cat('#', names(my_list)[i], '\n')
  cat('```{r}', '\n')

  cat('nrow(mylist[[i]])') #evaluate any other code here

  cat('\n')
  cat('```')
  cat('\n')
}
```

任何见解将不胜感激!

【问题讨论】:

  • 乍一看似乎是合理的,你有knit降价并看到结果是什么样的吗?你可能会看到这样做。
  • @r2evans 我尝试knit 降价并且标头很好,但代码块只是说nrow(mylist[[i]]) 并且它没有被评估

标签: r r-markdown


【解决方案1】:

此行为是因为 R 无法在所有 cat 调用创建的新环境中找到您的 mylist 对象。此外,由于mylist[[i]] 是一个表达式,我们必须对其进行解析和评估才能获得最终结果。

例如——

```{r headers, results = 'asis'}
for (i in seq_along(my_list)) {
  cat('#', names(my_list)[i], '\n')
  cat('```{r}', '\n')
  cat(eval(parse(text = 'i')))

  cat('\n')
  cat('```')
  cat('\n')
}
```

上面的代码会给出如下结果(这是我们需要的结果)-

# iris 
```{r} 
1
```
# airquality 
```{r} 
2
```
# mtcars 
```{r} 
3
```

但是要使用mylist 做到这一点,我们需要以某种方式确保 mylist 对象在新环境中,然后才能对其进行评估。另请注意,人们不鼓励使用parse(),因为它可能导致诸如此类的行为。更多在这里 - Assigning and removing objects in a loop: eval(parse(paste(

此答案适用于您的示例,但请考虑我提到的内容以及 SO 问题中的讨论 -

```{r data}
data("iris","airquality","mtcars")
my_list <- list(iris,airquality,mtcars)
names(my_list) <- c("iris","airquality","mtcars")
```

```{r headers, results = 'asis'}
for (i in seq_along(my_list)) {
  cat('#', names(my_list)[i], '\n')
  cat('```{r}', '\n')

  # somehow get the data or any other objects in here
  # this works for trivial examples please be carefule before using it on actual code chunks
  cat(eval(parse(text = paste(nrow(my_list[[i]])))))


  cat('\n')
  cat('```')
  cat('\n')
}
```

# iris 
```{r} 
150
```
# airquality 
```{r} 
153
```
# mtcars 
```{r} 
32
```

【讨论】:

  • 感谢您的解释 - 我应该回去阅读一下高级 R 环境一章。正如您所建议的,由于使用了parse,这种方法不会很好。我在SO post 中找到了另一种生成类似输出的方法。
  • 您是否介意发布一个您最终所做的小样本作为此问题的答案?我想每个人都会对这类问题感兴趣
  • 有机会我会制作一个样本
【解决方案2】:

这是我解决类似问题的一种方法。我在这里得到了关于 SO 的提示,但找不到答案...

两个文件:一个父母,一个孩子。把子文档想象成一个可以被多次调用的子程序,它的输出被保存(并连接到character 向量out)。完成该循环后,我使用内联 `r code` 块。

主文档,我猜是“父”:

---
output: md_document
---

```{r data}
data("iris","airquality","mtcars")
my_list <- list(iris,airquality,mtcars)
names(my_list) <- c("iris","airquality","mtcars")
```

```{r headers, echo = FALSE, include = FALSE, results = 'asis'}
out <- NULL
for (i in seq_along(my_list)) {
  out <- c(out, knitr::knit_child("somedoc-child.Rmd"))
}
```

`r paste(out, collapse="\n")`

子文档,同目录,上面称为somedoc-child.Rmd,由父文档调用。它看到的环境与父级离开时完全一样,因此可以完美地看到my_listi

# `r names(my_list[i])`

```{r, results="asis"}
nrow(my_list[[i]])
```

当我编织到降价时,我得到:

    data("iris","airquality","mtcars")
    my_list <- list(iris,airquality,mtcars)
    names(my_list) <- c("iris","airquality","mtcars")

iris
====

    nrow(my_list[[i]])

\[1\] 150

airquality
==========

    nrow(my_list[[i]])

\[1\] 153

mtcars
======

    nrow(my_list[[i]])

\[1\] 32

【讨论】:

  • 我喜欢使用child 文档的想法,这绝对是我需要阅读的内容。我最近找到了一种替代方法,可以使用knit_expand() 函数在此SO post 中创建类似的输出。感谢您的帮助
  • 这是另一种方法,我还没有看到。看起来差异很小,所以效果应该是一样的(特别是因为它们都将输出捕获到out 并在块之后转储它们)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多