You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:09:32