使用 R Markdown 在 for 循环中生成标签集

使用 R Markdown 在 for 循环中生成标签集

选项卡集是在 Markdown HTML 文件中嵌套内容的好方法,使用 for 循环可以让它们在输出中自动迭代。

R markdown 是与同事和主管分享您的工作、结果和代码的绝佳方式。您可以将文本、标题、表格、代码、对象和模型输出简化为格式整齐的文档,以便导出为 HTML 或 PDF。我定期将我的研究论文的更新和进展压缩成 HTML 文件,与我的主要教授分享。它让我可以解释我的思考过程,添加我编写的代码,并以有组织的方式立即显示输出以指导我们的会议。我目前正在使用 R markdown 来创建这个故事。

我在共享许多模型输出时遇到的一个问题是,整洁的文档格式很快就会变成一张巨大的滚动表,模型输出的页面令人作呕,难以导航。这让我想到了标签集。

标签集

Tabset 是一个 HTML 属性,它将内容嵌套到单独的、可单击的选项卡中。它不是每个输出都垂直扩展的文档,而是将相似的结果嵌套到由阅读器切换的选项卡中,从而节省了大量的屏幕空间。图为使用 ANOVA 模型分析的重复测量变量(哺乳期每周干物质摄入量)的示例。 tabset 不是按时间顺序打印每个模型摘要,而是允许我按标签对每周的结果进行分组。

Tabset 与 R Markdown 的标题层次结构原生集成,使其易于使用。 {.tabset} 在节标题的末尾输入,然后所有低于此初始标题级别的标题都将创建选项卡。这使您可以为选项卡集创建一个部分,并使用标题语法命名每个选项卡。确保在每个之间留一个空格,否则您的选项卡不会分开,并且要退出选项卡集,您需要一个空行和一个与选项卡集标题相同层次结构的新标题。

但是,如果您想使用标签集来压缩大量输出,而不是手动设置它们,您可以自动命名标签并在 for 循环中与输出一起生成它们。

R中的for循环

For 循环是强大的程序化迭代工具。您设置一个您希望在其上执行操作的范围,并为操作添加明确的指令以在该范围内的每个项目上执行。但是由于 R 已经是一种函数式编程语言,所以 for 循环通常被包装到其他函数中,或者完全被应用函数系列替换( 应用(), sapply(), lapply 等)或 purrr 包中的映射函数。这两个选项允许在一系列值之间轻松映射函数,而无需创建 for 循环并加快控制台中的计算时间。但是对于更详细的操作,我使用 for 循环在重复测量的每个时间点生成我想要呈现的所有模型输出,并将每个输出嵌套在单独的选项卡中。这种降价设置需要一些特定的元素和考虑因素,并将成为本故事的重点。

选项卡设置

我将从创建一个示例数据库开始。我们将生成 100 头具有唯一 ID 号的奶牛,并为它们分配泌乳数周内以千克为单位的牛奶重量值。这些奶牛都来自不同的奶牛场,所以我将分配一个奶牛场标签(1-5),然后按奶牛场将其制成表格,以便我们总结每个奶牛场中有多少奶牛。

(这些代码块是通过将您的 r 代码与 {r}(此处为代码) .我在设置 回声=真 作为一个选项,以便代码显示在降价文档中,以及打印输出,例如 头() 表和 桌子() 桌子。 回声=真 出现在括号 {} 中的 r 之后,因此您的代码块标题看起来像 {r,回声=真} )

 CowSample <- data.frame (CowID = c (sample (400: 599, 100, replace = FALSE)),  
 第 1 周 = c(runif(100, min=10, max=20)),  
 Week2 = c(runif(100, min=15, max=25)),  
 第 3 周 = c(runif(100, min=18, max=28)),  
 乳制品 = c(样本(1:5, 100, replace=TRUE)))  
 头部(CowSample) ## CowID Week1 Week2 Week3 乳制品  
 ## 1 422 17.49640 16.44578 22.65213 5  
 ## 2 550 10.75929 22.83381 21.01561 5  
 ## 3 494 17.19006 21.17778 24.92988 1  
 ## 4 445 13.10510 15.37010 21.21663 4  
 ## 5 556 19.33167 17.77398 19.20913 5  
 ## 6 569 18.97564 19.71178 19.12670 5  
 表(CowSample$乳制品  
 ##  
 ## 1 2 3 4 5  
 ## 18 19 19 25 19

现在,我想使用 ANOVA 模型分析不同奶牛场的产奶量平均值是否按周不同。我将打印模型摘要、每个级别均值的成对比较以及残差的 QQ 图,测试它们的正态性。

首先,我们需要将乳品向量设置为 data.frame 中的一个因子,以便我们可以在 ANOVA 中比较它的水平。

 CowSample$dairy <- as.factor(CowSample$dairy)  
 aov.week1 <- aov(Week1 ~ 乳制品,数据=CowSample)  
 摘要(aov.week1) ## Df Sum Sq Mean Sq F 值 Pr(>F)  
 ## 乳制品 4 24.0 6.007 0.672 0.613  
 ## 残差 95 849.6 8.943  
 情节(aov.week1,其中=2)

 TukeyHSD(aov.week1) ## Tukey 均值的多重比较  
 ## 95% 的家庭信心水平  
 ##  
 ## 拟合:aov(公式 = 第 1 周 ~ 乳制品,数据 = CowSample)  
 ##  
 ## $乳制品  
 ## diff lwr upr p adj  
 ## 2-1 1.03880065 -1.696589 3.774191 0.8283051  
 ## 3-1 -0.08801605 -2.823406 2.647374 0.9999852  
 ## 4-1 0.57689665 -1.993851 3.147644 0.9708759  
 ## 5-1 -0.32379637 -3.059186 2.411594 0.9974226  
 ## 3-2 -1.12681671 -3.824989 1.571355 0.7731743  
 ## 4-2 -0.46190401 -2.993014 2.069206 0.9864439  
 ## 5-2 -1.36259702 -4.060769 1.335575 0.6264059  
 ## 4-3 0.66491270 -1.866197 3.196022 0.9488705  
 ## 5-3 -0.23578032 -2.933952 2.462392 0.9992161  
 ## 5-4 -0.90069302 -3.431803 1.630417 0.8594171

我们看到该模型并不显着,第 1 周的牛奶平均值在 5 个不同的奶牛场中没有差异。我想每周继续进行此分析并提出相同的问题。我可以通过为每一列写出相同的模型代码来做到这一点,或者我可以让一个 for 循环在一个列范围内执行它。如果我想在标签集中手动设置每周,我可以在这里通过设置标题轻松地使用降价,然后为每个标签设置子标题。

## 牛奶分析 {.tabset}
### 第 1 周
(内容在这里)
### 第 2 周
(内容在这里)

退出标签集

请记住,我们需要一个与选项卡集的打开器相同层的标题才能退出,并确保以下内容不会卡在最后一个选项卡中。

在 for 循环中生成选项卡标题

前一种方法可用于少量选项卡或明确定义的内容。但是如果我们在一个大范围内循环一个函数,我们可以设置一些代码来在 for 循环中包含 tabset 标题。

这种方法引入了一个新的代码块选项。以前我设置 回声=真 在我的块头之后 {r} , 以指定我希望将代码包含在 HTML 输出中。这次我将启用 结果='asis' .它位于语言规范之后的其他块选项,用逗号分隔 ```{r,结果='asis'}```` .通常,knitr(将您的 R markdown 文件转换为 HTML 或 PDF 输出的包)逐字呈现代码并将其隔离在文档的块内: ``` ## print("Hello World") ```` 但是当我们设置 结果='asis' 代码将改为原始输出,没有围栏。通过创建被识别为子标题的原始输出并在我们的选项卡集中创建一个选项卡,我们可以在创建选项卡集时利用这一点。为了说明这一点,我将为带编号的标签集标题创建一个变量,并在 for 循环中打印它。因为代码是“asis”输出并且没有被代码块隔离,所以输出将被先前建立的带有 {.tabset} 属性的标签集标题拾取并收集到标签中。

示例标签集

 一个 <- 0  
 **为了** (一世 **在** 1:10){  
 一 <- 一 + 1  
 cat("#### 标签号", a, "\n")  
 猫(“\n”)  
 cat("这是标签号", a, "\n")  
 猫(“\n”)  
 print("你好世界\n")  
 猫(“\n”)  
 摘要(aov.week1)  
 }

新的考虑

上面的代码现在正在循环一个长度为 10 的变量。我设置 一个 在 for 循环之前为 0,并将每个循环作为一种计数增加 1。我可以直接在我的输出中调用变量,所以我设置 一个 在命名我的每个选项卡的函数中间。注意如何 猫() 函数包装文本输出。因为我们使用的是 结果=asis 块选项代码作为原始降价输出,如果我想在输入字符时输出字符,它需要进入 猫() .我还需要使用 打印() 函数获取显示在下面的函数的输出 结果=asis 选项,否则,不会返回任何内容。你可以看到我包括 上面的 print("Hello world") 并得到了代码输出,但是 摘要(aov.week1) 什么也没返回,即使它通常会给我模型表输出,如果 结果=asis 没有打开。相反,我需要将其包装为 打印(摘要(aov.week1))`。

另一个考虑是使用 "\n" .你看上面 "\n" 自由地出现在代码中。这对于安抚选项卡集标题层次结构的格式是必要的。 "\n" 在行尾返回换行符, 猫(“\n”) 在单独的行上给我一个空行。当 for 循环返回原始代码输出时,语句末尾没有换行符,并且子标题和内容之间有一个空行,则将违反制表符格式,并且它不会将每个子标题作为新的制表符输入捕获,如输出将被连接在一起,而不是作为新标题分开。

在循环中包含模型

接下来,我想在我之前创建的列范围内建立一些模型构建。无需每次都重写模型方程,我可以将其包装在 for 循环中并为我执行此操作。我将构建一个遍历列范围并使用列值作为模型输入的 for 循环。我还想计算每次迭代,并将每个模型保存为单独的变量,而不是将结果替换为循环的新迭代。为此,我将使用分配和粘贴功能。

 b <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 b <- b + 1  
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
 分配(粘贴0(“方差分析”,b),模型,pos = 1)  
 } 方差分析 1 ## 称呼:  
 ## aov(公式 = i ~ 乳制品,数据 = CowSample)  
 ##  
 ## 条款:  
 ## 乳制品残留物  
 ## 平方和 24.0271 849.6240  
 ##度数自由的 4 95  
 ##  
 ## 残留标准误差:2.990554  
 ## 估计效果可能不平衡 方差分析2 ## 称呼:  
 ## aov(公式 = i ~ 乳制品,数据 = CowSample)  
 ##  
 ## 条款:  
 ## 乳制品残留物  
 ## 平方和 58.1810 851.4166  
 ##度数自由的 4 95  
 ##  
 ## 残留标准误差:2.993707  
 ## 估计效果可能不平衡 方差分析.3 ## 称呼:  
 ## aov(公式 = i ~ 乳制品,数据 = CowSample)  
 ##  
 ## 条款:  
 ## 乳制品残留物  
 ## 平方和 32.8880 749.6091  
 ##度数自由的 4 95  
 ##  
 ## 残留标准误差:2.809025  
 ## 估计效果可能不平衡

为了在牛奶周的每一列中循环我的模型函数,我使用索引调用列 牛样本 [, 2: 4] ,因为第 1、2 和 3 周位于列索引 2,3 和 4。2:4 之前的逗号是必不可少的,因为它表示我们正在索引列,行索引位于列之前,它们用逗号分隔。由于我们包含所有行并调用特定列,因此我们在逗号之前不包含任何变量。

我再次使用计数器变量 b 在这里为输出分配编号的名称。随着 分配() 功能,我正在更改名称 模型 通过将计数器添加到名称中,将在每个循环中创建的变量添加到唯一标识符 粘贴0() .这可确保我的环境为循环的每次运行保存一个唯一模型,而不是像通常那样替换前一个模型。如果我只想在选项卡中打印每个模型,这不是必需的,但如果我想保存每个模型以供以后使用,这可能很重要。

在循环标签集中打印模型输出

最后,我将讨论在上述选项卡集中输出模型信息的一些注意事项。由于我们需要使用 结果=asis 为了让 tabset 标头捕获我们的选项卡名称,我们的一些模型描述输出将无法在块中按预期工作。我之前提到过需要将函数包装在 打印() 函数,否则它们将不会返回任何内容。让我们现在试试 摘要(型号) .

带有模型摘要的牛奶中的按周方差分析

 c <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 c <- c + 1  
 cat("##### 周", c, "\n")  
 猫(“\n”)  
 cat("这是一周内牛奶的方差分析", a, "\n")  
 猫(“\n”)  
    
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
    
 current.model <-assign(paste0("Anova.", c), model, pos=1)  
 打印(摘要(current.model))  
 猫(“\n”)  
 }

没有按预期工作

不要忘记 猫(“\n”) 最后,否则您的选项卡将全部合并为一个。您可以看到模型摘要的表格没有正常输出并且变成了丑陋的混淆。我有两种可能的解决方案。

  1. 使用包参数中的 HTML 格式表
  2. 使用 Knitr 将您的输出转换为降价表作为 kable

1.参数包

参数包提供了一些有吸引力的模型摘要,可以在 HTML 中本地打印,并且适合我们在 结果=asis 选项。

如果您在降价中包含用于加载库的代码,我建议将代码块选项设置为 {r,警告=FALSE,消息=FALSE} 以便库中的任何消息都隐藏在您的输出中。

_#install.packages("参数")_  
 **图书馆** (参数)

现在我将重新运行之前的 for 循环并尝试 print_html 模型参数 来自参数包。

模型输出固定的牛奶中按周进行的方差分析

 c <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 c <- c + 1  
 cat("##### 周", c, "\n")  
 猫(“\n”)  
 cat("这是一周内牛奶的方差分析", a, "\n")  
 猫(“\n”)  
    
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
    
 current.model <-assign(paste0("Anova.", c), model, pos=1)  
 print(print_html(model_parameters(current.model, summary=TRUE)))  
 猫(“\n”)  
 }

现在,我们有了这个包的 HTML 格式汇总表的更具吸引力和可读性的输出。

但是,我之前构建的用于检查每个组之间差异的 tukey 表是一个不适合“model_parameters”函数的对象。相反,我将使用 tidyverse 包将其转换为对降价友好的 kable。

2. Kables 代替表格

早些时候,当我生成 tukey 分析时,我们打印了一个包含结果的表格。但是这个对象的类不容易被操纵。

 CowSample$dairy <- as.factor(CowSample$dairy)  
 aov.week1 <- aov(Week1 ~ 乳制品,数据=CowSample)  
 tukey <- TukeyHSD(aov.week1)  
 图基 ## Tukey 均值的多重比较  
 ## 95% 的家庭信心水平  
 ##  
 ## 拟合:aov(公式 = 第 1 周 ~ 乳制品,数据 = CowSample)  
 ##  
 ## $乳制品  
 ## diff lwr upr p adj  
 ## 2-1 1.03880065 -1.696589 3.774191 0.8283051  
 ## 3-1 -0.08801605 -2.823406 2.647374 0.9999852  
 ## 4-1 0.57689665 -1.993851 3.147644 0.9708759  
 ## 5-1 -0.32379637 -3.059186 2.411594 0.9974226  
 ## 3-2 -1.12681671 -3.824989 1.571355 0.7731743  
 ## 4-2 -0.46190401 -2.993014 2.069206 0.9864439  
 ## 5-2 -1.36259702 -4.060769 1.335575 0.6264059  
 ## 4-3 0.66491270 -1.866197 3.196022 0.9488705  
 ## 5-3 -0.23578032 -2.933952 2.462392 0.9992161  
 ## 5-4 -0.90069302 -3.431803 1.630417 0.8594171 类(tukey) ## [1] "TukeyHSD" "multicomp"

当我尝试在 结果=asis 选项让我们看看结果。

牛奶中的每周方差分析和 tukey 分析

 c <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 c <- c + 1  
 cat("##### 周", c, "\n")  
 猫(“\n”)  
 cat("这是一周内牛奶的方差分析", a, "\n")  
 猫(“\n”)  
    
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
    
 current.model <-assign(paste0("Anova.", c), model, pos=1)  
 打印(TukeyHSD(current.model))  
 猫(“\n”)  
 }

出来的不是很清晰。

这次我们将获取 tukey 对象并使用 tidyverse 包将其转换为 tibble。 Kables 是来自 Knitr 包的一种表格,它为降价渲染制作了非常简单的表格。通过将我们的 tukey 对象转换为其中之一,也许我们可以提高可读性。

首先我会 整齐的() 使用 broom 包将 Tukey 输出到 data.frame,并加载 knitr 包以使用 电缆() 功能。

_#install.packages("扫帚")_  
 **图书馆** (扫帚)  
 **图书馆** (编织者)

与 tukey Kable 一起在牛奶中按周进行方差分析

 c <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 c <- c + 1  
 cat("##### 周", c, "\n")  
 猫(“\n”)  
 cat("这是一周内牛奶的方差分析", a, "\n")  
 猫(“\n”)  
    
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
    
 current.model <-assign(paste0("Anova.", c), model, pos=1)  
 tukey <- tidy(TukeyHSD(current.model))  
 打印(kable(tukey))  
 猫(“\n”)  
 }

这次我们设法打印了一个格式更好的表格来解释我们的 tukey 分析。

不幸的是,data.frame 转换引入了一些不必要的列和标题。我们可以通过添加“kableExtra”包中的选项来使用一些 kable 格式来清理它。我将使用排除无用的列 选择() 来自 tidyverse,然后添加一些有用的列名。

与 tukey Kable 一起在牛奶中按周进行方差分析

_#install.packages("tidyverse)_  
 _#install.packages("kableExtra)_  
 **图书馆** (tidyverse)  
 **图书馆** (电缆额外)  
 c <- 0  
 **为了** (一世 **在** CowSample [, 2: 4]) {  
 c <- c + 1  
 cat("##### 周", c, "\n")  
 猫(“\n”)  
 cat("这是一周内牛奶的方差分析", a, "\n")  
 猫(“\n”)  
    
 模型 <- aov(i ~ 乳制品,数据=CowSample)  
    
 current.model <-assign(paste0("Anova.", c), model, pos=1)  
 tukey <- tidy(TukeyHSD(current.model))  
 tukey <- tukey %>% dplyr::select(-term, -null.value)  
 打印(kable(tukey,col.names=c(“对比度”,“差异”,“下 CI”,“上 CI”,“*P*-值”))%>%  
 kable_styling() %>% scroll_box(height = "500px"))  
 猫(“\n”)  
 }

包起来

在这个故事中,我们探索了在 markdown 格式中使用选项卡集来组织选项卡式 HTML 窗格中的输出。我演示了如何使用代码块选项 结果=asis 可用于生成标头作为代码输出,并为每次运行 for 循环自动生成新选项卡。最后,我讨论了在处理由 结果=asis ,以及如何在此环境中格式化和呈现您的对象而不会失去可读性。

感谢您阅读并遵循我在 Medium 上的 R 技巧。

帕特里克

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/5796/01030100

posted @ 2022-09-01 00:01  哈哈哈来了啊啊啊  阅读(229)  评论(0编辑  收藏  举报