flexdashboard中第二个绘图远小于第一个的原因及解决方法
问题原因
你遇到的第二个图尺寸偏小的问题,本质是flexdashboard的排版引擎在处理动态生成的Markdown+绘图内容时出现了适配异常:
- 你用
results="asis"让循环直接输出Markdown标题(#### foo这类)和绘图,第一个绘图能正确读取chunk开头设置的fig.height/fig.width参数,生成对应尺寸的容器; - 但循环后续输出的内容,因为Markdown标题和绘图的衔接没有被flexdashboard正确识别为独立的“内容块”,导致后续绘图的容器尺寸被自动压缩,无法继承预设的图形尺寸参数。
解决方法
这里提供3种可行的方案,按简单程度排序:
方案1:给每个绘图包裹固定高度的HTML容器
在循环里打印绘图前后,手动添加固定高度的div容器,强制每个绘图的显示区域一致:
--- title: "Reprex" output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: scroll --- My Tab ======================================================================= ```{r include=TRUE, results="asis", echo=FALSE, fig.height=3, fig.width=5} library(dplyr) library(ggplot2) dat <- tribble( ~item, ~subitem, ~x, ~y, 'foo', 'a', 3.2, 101, 'foo', 'a', 2.2, 94, 'foo', 'a', 1.2, 32, 'foo', 'b', 12.2, 49, 'foo', 'b', 0.2, 83, 'foo', 'b', 7.7, 29, 'bar', 'a', 13.2, 10, 'bar', 'a', 7.0, 8, 'bar', 'a', 0.1, 100, 'bar', 'b', 10.2, 93, 'bar', 'b', 4.0, 74, 'bar', 'b', 10.3, 35 ) items <- unique(dat$item) for(i in items){ cat("\n") cat(paste("####", i, "\n")) cat("\n") # 添加固定高度的div容器 cat('<div style="height:280px; margin-bottom:20px;">') p <- ggplot(filter(dat, item == i), aes(x, y)) + geom_point() + facet_wrap(~subitem) print(p) cat('</div>') cat("\n") } cat("\n")
这里的`height:280px`对应`fig.height=3`的大致像素高度(默认dpi 96时,3*96=288,取近似值即可),可根据需求调整。 ## 方案2:循环中重新设置knitr图形参数 在每次打印绘图前,手动重置knitr的当前chunk图形参数,确保每个绘图都能读取到尺寸设置: ```r --- title: "Reprex" output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: scroll --- My Tab ======================================================================= ```{r include=TRUE, results="asis", echo=FALSE} library(dplyr) library(ggplot2) library(knitr) dat <- tribble( ~item, ~subitem, ~x, ~y, 'foo', 'a', 3.2, 101, 'foo', 'a', 2.2, 94, 'foo', 'a', 1.2, 32, 'foo', 'b', 12.2, 49, 'foo', 'b', 0.2, 83, 'foo', 'b', 7.7, 29, 'bar', 'a', 13.2, 10, 'bar', 'a', 7.0, 8, 'bar', 'a', 0.1, 100, 'bar', 'b', 10.2, 93, 'bar', 'b', 4.0, 74, 'bar', 'b', 10.3, 35 ) items <- unique(dat$item) for(i in items){ cat("\n") cat(paste("####", i, "\n")) cat("\n") # 每次循环都重置图形尺寸参数 opts_current$set(fig.height=3, fig.width=5) p <- ggplot(filter(dat, item == i), aes(x, y)) + geom_point() + facet_wrap(~subitem) print(p) cat("\n") } cat("\n")
## 方案3:改用knit_child生成独立内容块 如果需要更规范的动态内容生成,可以用`knitr::knit_child`把每个绘图和标题放在独立的子文档里,让flexdashboard正确识别每个内容块: 1. 创建子文档`plot_chunk.Rmd`: ```md #### `r i` ```{r} p <- ggplot(filter(dat, item == i), aes(x, y)) + geom_point() + facet_wrap(~subitem) print(p)
2. 主文档调用: ```r --- title: "Reprex" output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: scroll --- My Tab ======================================================================= ```{r include=TRUE, results="asis", echo=FALSE, fig.height=3, fig.width=5} library(dplyr) library(ggplot2) library(knitr) dat <- tribble( ~item, ~subitem, ~x, ~y, 'foo', 'a', 3.2, 101, 'foo', 'a', 2.2, 94, 'foo', 'a', 1.2, 32, 'foo', 'b', 12.2, 49, 'foo', 'b', 0.2, 83, 'foo', 'b', 7.7, 29, 'bar', 'a', 13.2, 10, 'bar', 'a', 7.0, 8, 'bar', 'a', 0.1, 100, 'bar', 'b', 10.2, 93, 'bar', 'b', 4.0, 74, 'bar', 'b', 10.3, 35 ) items <- unique(dat$item) for(i in items){ cat(knit_child("plot_chunk.Rmd", quiet = TRUE)) }
内容的提问来源于stack exchange,提问作者jmuhlenkamp
相关产品推荐
相关产品推荐

