英文:
r markdown change separator between specific unnamed code blocks from line breaks to a space
问题
我有一个R Markdown报告(使用officedown::rdocx_document
输出为MS Word),其中包含顶部的一个摘要段落。它描述了基于我的数据的确诊、可能和可能病例的数量。
但是,如果这些类别中的任何一种病例数量为0,我需要抑制该类别的句子。如果病例数量大于0,我需要显示该句子,但还需要应用一些内联代码,根据另一个条件对数字进行着色,使用officer::ftext()
和我在之前的代码块中创建的officer::fp_text()
样式。应用这个条件文本颜色的代码有点复杂,无法在R对象中保存文本样式,只能在呈现文档时应用。
我能够根据Yihui Xie在类似问题上的回答这里来有条件地抑制句子。这个方法效果很好,并且有条件的文本着色得以保留。
然而,由于这种方法将每个要有条件抑制的句子放在自己的代码块中,它们被呈现为单独的段落,并在它们之间插入了空行。
我正在寻找的是一种将非条件文本与由代码块创建的有条件句子合并到一个单独段落的方法。我认为这意味着将这些特定代码块之间的分隔符从默认值'\n\n'
更改为' '
。我尝试使用这个SO帖子中建议的lua过滤器,但使用'\s'
会引发错误并停止编织,而使用纯空格作为code_block_sep
则会被忽略,不起作用。
local code_block_sep = ' '
function Blocks (blocks)
for i = #blocks, 2, -1 do -- 从列表末尾开始
-- 两个块都必须是代码块,并且共享相同的主要类别
if blocks[i - 1].t == 'CodeBlock' and
blocks[i].t == 'CodeBlock' and
blocks[i - 1].classes[1] == blocks[i].classes[1] then
blocks[i - 1].text = blocks[i - 1].text ..
code_block_sep ..
blocks[i].text
blocks:remove(i)
end
end
return blocks
end
有没有办法去除换行,使非条件和有条件的句子都出现在同一段落中?
以下是一些示例代码。
首先,我在我的R Markdown设置块中添加knit选项:
```{r setup, include=FALSE}
# 加载knitr库:
library(knitr)
# 设置选项以接受包含内联代码的条件显示/隐藏文本:
knit_engines$set(asis = function(options) {
if (options$echo && options$eval) knit_child(text = options$code)
})
接下来,在一个代码块中添加一些示例数据:
```{r egdata}
# 确诊病例数量
n_confirmed <- 14
# 可能病例数量
n_probable <- 0
# 可能病例数量
n_possible <- 5
现在,在另一个代码块中创建条件:
```r
```{r conditions}
# 创建显示或隐藏确诊病例句子的条件:
if(n_confirmed > 0){showconf <- TRUE} else {showconf <- FALSE}
# 创建显示或隐藏可能病例句子的条件:
if(n_probable > 0){showprob <- TRUE} else {showprob <- FALSE}
# 创建显示或隐藏可能病例句子的条件:
if(n_possible > 0){showposs <- TRUE} else {showposs <- FALSE}
现在,我以非条件文本开始我的段落:
```markdown
This summary describes the number of cases by case definition.
最后,我添加有条件的句子(使用加法来说明内联代码):
```{asis, echo=showconf}
There are *n* = `r n_confirmed + 1` confirmed cases.
There are *n* = `r n_probable + 1` probable cases.
There are *n* = `r n_possible + 1` possible cases.
我希望编织后的文本以如下的方式显示在单一段落中:
> This summary describes the number of cases by case definition. There are *n* = 15 confirmed cases. There are *n* = 6 possible cases.
<details>
<summary>英文:</summary>
I have an r markdown report (output is MS word using `officedown::rdocx_document`) which includes a paragraph of summary text at the top. It describes the number of confirmed, probable and possible cases based on my data.
However, if the number of cases for any of these categories is 0, I need to supress the sentence for that category. If the number of cases is greater than 0, I need to show the sentence, but also apply some inline code that colours the number based on another condition, using `officer::ftext()` and a `officer::fp_text()` style that I created in an earlier chunk. The code to apply this conditional text colour is a bit complex to reproduce here, but the main point is that the text style cannot be saved in an R object. It is only applied on rendering the document.
I was able to conditionally suppress sentences by following Yihui Xie's answer to a similar question [here](https://stackoverflow.com/questions/32944715/conditionally-display-block-of-markdown-text-using-knitr). This works well, and the conditional text colouring is preserved.
However - because this method puts each sentence to conditionally suppress in its own chunk, they are rendered as separate paragraphs with an empty line in between each one.
What I am looking for is a way to combine the non conditional text outside the code chunks, with the conditional sentences created by the code chunks in one single paragraph. I *think* this means changing the separator between these specific code chunks from the default `'\n\n'` to `' '`. I tried with a lua filter as suggested in [this SO post](https://stackoverflow.com/questions/72878908/can-i-merge-the-code-of-successive-code-chunks-with-no-output-echoed-in-a-rmarkd) but using `'\s'` throws an error and halts the knitting, while using a plain space for the `code_block_sep` is just ignored and does nothing.
```lua
local code_block_sep = ' '
function Blocks (blocks)
for i = #blocks, 2, -1 do -- start at end of list
-- Both blocks must be code blocks and share the same primary class
if blocks[i - 1].t == 'CodeBlock' and
blocks[i].t == 'CodeBlock' and
blocks[i - 1].classes[1] == blocks[i].classes[1] then
blocks[i - 1].text = blocks[i - 1].text ..
code_block_sep ..
blocks[i].text
blocks:remove(i)
end
end
return blocks
end
Is there a way to remove the line breaks so that the non-conditional and conditional sentences all appear in the same paragraph?
Here is some example code.
First, I add the knit option to my r markdown setup chunk:
```{r setup, include=FALSE}
# Load knitr library:
library(knitr)
# Set options to accept conditional show/hide with text containing inline code:
knit_engines$set(asis = function(options) {
if (options$echo && options$eval) knit_child(text = options$code)
})
```
Next, I add some example data in a code chunk:
```{r egdata}
# Number of confirmed cases
n_confirmed <- 14
# Number of probable cases
n_probable <- 0
# Number of possible cases
n_possible <- 5
```
Now I create the conditions in another code chunk:
```{r conditions}
# Create condition to show or hide confirmed cases sentence:
if(n_confirmed > 0){showconf <- TRUE} else {showconf <- FALSE}
# Create condition to show or hide probable cases sentence:
if(n_probable > 0){showprob <- TRUE} else {showprob <- FALSE}
# Create condition to show or hide possible cases sentence:
if(n_possible > 0){showposs <- TRUE} else {showposs <- FALSE}
```
Now I start my paragraph with the non-conditional text:
This summary describes the number of cases by case definition.
Finally I add the conditional sentences (using addition to illustrate the inline code):
```{asis, echo=showconf}
There are *n* = `r n_confirmed + 1` confirmed cases.
```
```{asis, echo=showprob}
There are *n* = `r n_probable + 1` probable cases.
```
```{asis, echo=showposs}
There are *n* = `r n_possible + 1` possible cases.
```
I would like the text when knitted to print in a single paragraph like this:
> This summary describes the number of cases by case definition. There are n = 15 confirmed cases. There are n = 6 possible cases.
答案1
得分: 1
你可以使用 list()
和 do.call()
来创建一个由 ftext()
对象构成的 fpar()
对象。
library(officer)
compare <- data.frame(name = c("n_total", "n_children", "n_adults"),
value_new = c(50, 0, 50),
value_old = c(45, 0, 45),
change = c(TRUE, FALSE, TRUE))
fp_default <- fp_text(font.size = 10, font.family = "Calibri")
fp_emphasized <- update(fp_default, color = "#4F81BD", bold = TRUE)
out <- list()
if( any(compare$change)) {
out <- append(
out,
list(ftext("This is a summary paragraph describing the cases by agegroup.", fp_default))
)
}
is_n_total <- compare$name %in% "n_total"
if( compare$change[is_n_total] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_total], fp_emphasized),
ftext(" cases in total.", fp_default)
)
)
}
is_n_children <- compare$name %in% "n_children"
if( compare$change[is_n_children] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_children], fp_emphasized),
ftext(" children.", fp_default)
)
)
}
is_n_adults <- compare$name %in% "n_adults"
if( compare$change[is_n_adults] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_adults], fp_emphasized),
ftext(" adults.", fp_default)
)
)
}
your_paragraph <- do.call(fpar, out)
在R Markdown文档中:
---
output: officedown::rdocx_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.cap = TRUE)
library(officedown)
library(officer)
compare <- data.frame(name = c("n_total", "n_children", "n_adults"),
value_new = c(50, 0, 50),
value_old = c(45, 0, 45),
change = c(TRUE, FALSE, TRUE))
fp_default <- fp_text(font.size = 10, font.family = "Calibri")
fp_emphasized <- update(fp_default, color = "#4F81BD", bold = TRUE)
out <- list()
if( any(compare$change)) {
out <- append(
out,
list(ftext("This is a summary paragraph describing the cases by agegroup.", fp_default))
)
}
is_n_total <- compare$name %in% "n_total"
if( compare$change[is_n_total] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_total], fp_emphasized),
ftext(" cases in total.", fp_default)
)
)
}
is_n_children <- compare$name %in% "n_children"
if( compare$change[is_n_children] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_children], fp_emphasized),
ftext(" children.", fp_default)
)
)
}
is_n_adults <- compare$name %in% "n_adults"
if( compare$change[is_n_adults] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_adults], fp_emphasized),
ftext(" adults.", fp_default)
)
)
}
do.call(fpar, out)
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/YGa8Z.png
[2]: https://i.stack.imgur.com/kqGIs.png
<details>
<summary>英文:</summary>
You can use `list()` and `do.call()` to create an `fpar()` object made of `ftext()` objects.
library(officer)
compare <- data.frame(name = c("n_total", "n_children", "n_adults"),
value_new = c(50, 0, 50),
value_old = c(45, 0, 45),
change = c(TRUE, FALSE, TRUE))
fp_default <- fp_text(font.size = 10, font.family = "Calibri")
fp_emphasized <- update(fp_default, color = "#4F81BD", bold = TRUE)
out <- list()
if( any(compare$change)) {
out <- append(
out,
list(ftext("This is a summary paragraph describing the cases by agegroup.", fp_default))
)
}
is_n_total <- compare$name %in% "n_total"
if( compare$change[is_n_total] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_total], fp_emphasized),
ftext(" cases in total.", fp_default)
)
)
}
is_n_children <- compare$name %in% "n_children"
if( compare$change[is_n_children] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_children], fp_emphasized),
ftext(" children.", fp_default)
)
)
}
is_n_adults <- compare$name %in% "n_adults"
if( compare$change[is_n_adults] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_adults], fp_emphasized),
ftext(" adults.", fp_default)
)
)
}
your_paragraph <- do.call(fpar, out)
see the result in RStudio Viewer
your_paragraph |> to_html() |> htmltools::HTML() |> htmltools::browsable()
[![enter image description here][1]][1]
In an R Markdown document:
output: officedown::rdocx_document
knitr::opts_chunk$set(echo = TRUE, fig.cap = TRUE)
library(officedown)
library(officer)
compare <- data.frame(name = c("n_total", "n_children", "n_adults"),
value_new = c(50, 0, 50),
value_old = c(45, 0, 45),
change = c(TRUE, FALSE, TRUE))
fp_default <- fp_text(font.size = 10, font.family = "Calibri")
fp_emphasized <- update(fp_default, color = "#4F81BD", bold = TRUE)
out <- list()
if( any(compare$change)) {
out <- append(
out,
list(ftext("This is a summary paragraph describing the cases by agegroup.", fp_default))
)
}
is_n_total <- compare$name %in% "n_total"
if( compare$change[is_n_total] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_total], fp_emphasized),
ftext(" cases in total.", fp_default)
)
)
}
is_n_children <- compare$name %in% "n_children"
if( compare$change[is_n_children] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_children], fp_emphasized),
ftext(" children.", fp_default)
)
)
}
is_n_adults <- compare$name %in% "n_adults"
if( compare$change[is_n_adults] ) {
out <- append(
out,
list(
ftext(" There were ", fp_default),
ftext(compare$value_new[is_n_adults], fp_emphasized),
ftext(" adults.", fp_default)
)
)
}
do.call(fpar, out)
[![enter image description here][2]][2]
[1]: https://i.stack.imgur.com/YGa8Z.png
[2]: https://i.stack.imgur.com/kqGIs.png
</details>
# 答案2
**得分**: 0
我会使用`if`语句在一个代码块中构建句子,然后在另一个代码块中使用`asis`打印它们。例如:
```{r, echo=FALSE}
phrases <- "这个摘要描述了根据病例定义的病例数量。"
if (showconf) {
phrases <- paste(phrases, "有 *n* =", n_confirmed + 1, "例确诊病例。")
}
if (showprob) {
phrases <- paste(phrases, "有 *n* =", n_probable + 1, "例可能病例。")
}
if (showposs) {
phrases <- paste(phrases, "有 *n* =", n_possible + 1, "例可能病例。")
}
```
```{r, results="asis", echo=FALSE}
cat(phrases)
```
这将得到以下结果:
[![句子的截图][1]][1]
[1]: https://i.stack.imgur.com/w4MEM.png
<details>
<summary>英文:</summary>
I would construct the sentences in one r chunk using `if` statements and then print them using `asis` in a different chunk. For example:
````
```{r, echo=FALSE}
phrases <- "This summary describes the number of cases by case definition."
if (showconf) {
phrases <- paste(phrases, "There are *n* =", n_confirmed + 1, "confirmed cases.")
}
if (showprob) {
phrases <- paste(phrases, "There are *n* =", n_probable + 1, "probable cases.")
}
if (showposs) {
phrases <- paste(phrases, "There are *n* =", n_possible + 1, "possible cases.")
}
```
```{r, results="asis", echo=FALSE}
cat(phrases)
```
````
which gives:
[![screenshot of sentence][1]][1]
[1]: https://i.stack.imgur.com/w4MEM.png
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论