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

R Markdown循环中multicol环境下表格与图表排版问题求助

title: "Untitled"
header-includes:

  • \usepackage{multicol}
  • \usepackage[labelformat = empty]{caption}
    output:
    pdf_document:
    keep_tex: true

```{r cars, echo=FALSE, results='asis'}
library(ggplot2)

tables1 <- list()
tables2 <- list()
tables3 <- list()
tables4 <- list()
plots1 <- list()
plots2 <- list()
plots3 <- list()

categories <- c("A","B","C")

for (cat in categories){
tables1[[cat]] <- head(iris)
tables2[[cat]] <- head(cars)
tables3[[cat]] <- head(mtcars)
tables4[[cat]] <- head(ToothGrowth)
plots1[[cat]] <- ggplot(cars)
plots2[[cat]] <- ggplot(mtcars)
plots3[[cat]] <- ggplot(ToothGrowth)
}

for (cat in categories){
  table1 <- tables1[[cat]]
  table2 <- tables2[[cat]]
  table3 <- tables3[[cat]]
  table4 <- tables4[[cat]]
  plot1 <- plots1[[cat]]
  plot2 <- plots2[[cat]]
  plot3 <- plots3[[cat]]
  
  #then i format all the tables with kableExtra, removing the "table" enviroment
  
  cat("\\newpage\n") #a page for each category, containing all the plots and tables in the same order
  cat("\\fontsize{11}{13}\\selectfont\n")
  cat(cat, "\n") #title should be the name of the category
  cat("\\vspace*{-0.1cm}\\n\\n")
  print(table1) #full-width table
  cat("\\setlength{\\columnsep}{25pt}\\n")
  #full-width header
  cat("\\begin{multicols}{2}\\n")
  print(table2)
  cat("\\columnbreak\\n")
  cat("\\begin{center}\\n")
  print(plot1)
  cat("\\end{center}\\n")
  cat("\\end{multicols}\\n")
  #full-width header
  cat("\\begin{multicols}{2}\\n")
  print(table3)
  cat("\\columnbreak\\n")
  cat("\\begin{center}\\n")
  print(plot2)
  cat("\\end{center}\\n")
  cat("\\end{multicols}\\n")
  #full-width header
  cat("\\begin{multicols}{2}\\n")
  print(table4)
  cat("\\columnbreak\\n")
  cat("\\begin{center}\\n")
  print(plot3)
  cat("\\end{center}\\n")
  cat("\\end{multicols}\\n")
}

解决方法

核心问题是ggplot默认生成浮动figure环境,与multicol配合时会脱离预期位置。通过修改knitr图表输出选项、添加非浮动标题命令可解决:

1. 调整YAML依赖(可选增强)

保留原有包,可添加float包辅助位置控制:

---
title: "Untitled"
header-includes:
  - \usepackage{multicol}
  - \usepackage[labelformat = empty]{caption} 
  - \usepackage{float}
output:
  pdf_document:
    keep_tex: true
---

2. 修改R代码块

在循环中临时取消图表浮动环境,用captionof添加标题,同时调整表格样式适配multicol:

library(ggplot2)
library(kableExtra)

# 初始化列表并格式化表格/图表
tables1 <- list()
tables2 <- list()
tables3 <- list()
tables4 <- list()
plots1 <- list()
plots2 <- list()
plots3 <- list()

categories <- c("A","B","C")

for (cat in categories){
  tables1[[cat]] <- head(iris) %>% kbl() %>% kable_styling(full_width = FALSE, position = "left")
  tables2[[cat]] <- head(cars) %>% kbl() %>% kable_styling(full_width = FALSE, position = "left")
  tables3[[cat]] <- head(mtcars) %>% kbl() %>% kable_styling(full_width = FALSE, position = "left")
  tables4[[cat]] <- head(ToothGrowth) %>% kbl() %>% kable_styling(full_width = FALSE, position = "left")
  plots1[[cat]] <- ggplot(cars, aes(speed, dist)) + geom_point() + ggtitle("Plot 1")
  plots2[[cat]] <- ggplot(mtcars, aes(mpg, disp)) + geom_point() + ggtitle("Plot 2")
  plots3[[cat]] <- ggplot(ToothGrowth, aes(len, supp)) + geom_boxplot() + ggtitle("Plot 3")
}

# 循环生成每页内容
for (cat in categories){
  table1 <- tables1[[cat]]
  table2 <- tables2[[cat]]
  table3 <- tables3[[cat]]
  table4 <- tables4[[cat]]
  plot1 <- plots1[[cat]]
  plot2 <- plots2[[cat]]
  plot3 <- plots3[[cat]]
  
  # 每页开头
  cat("\\newpage\n")
  cat("\\fontsize{11}{13}\\selectfont\n")
  cat("\\textbf{", cat, "}\n", sep = "")
  cat("\\vspace*{-0.1cm}\n\n")
  
  # 全宽表格
  print(table1)
  cat("\\vspace{0.5cm}\n")
  
  # 第一组:Table 2 + Plot 1
  cat("\\setlength{\\columnsep}{25pt}\n")
  cat("\\begin{multicols}{2}\n")
  print(table2)
  cat("\\columnbreak\n")
  # 取消浮动环境,输出图表并添加标题
  knitr::opts_current$set(fig.env = "", fig.pos = "", out.width = "100%")
  print(plot1)
  cat("\\captionof{figure}{", plot1$labels$title, "}\n", sep = "")
  cat("\\end{multicols}\n")
  cat("\\vspace{0.5cm}\n")
  
  # 第二组:Plot 2 + Table 3(匹配预期布局)
  cat("\\begin{multicols}{2}\n")
  knitr::opts_current$set(fig.env = "", fig.pos = "", out.width = "100%")
  print(plot2)
  cat("\\captionof{figure}{", plot2$labels$title, "}\n", sep = "")
  cat("\\columnbreak\n")
  print(table3)
  cat("\\end{multicols}\n")
  cat("\\vspace{0.5cm}\n")
  
  # 第三组:Table 4 + Plot 3
  cat("\\begin{multicols}{2}\n")
  print(table4)
  cat("\\columnbreak\n")
  knitr::opts_current$set(fig.env = "", fig.pos = "", out.width = "100%")
  print(plot3)
  cat("\\captionof{figure}{", plot3$labels$title, "}\n", sep = "")
  cat("\\end{multicols}\n")
}

关键修改说明

  • 取消浮动环境:通过knitr::opts_current$set(fig.env = "", fig.pos = "")让图表直接嵌入当前位置,不生成浮动figure。
  • 添加图表标题:用\captionof{figure}{标题}在multicol内添加标题,规避浮动环境限制。
  • 表格适配:设置kable表格full_width = FALSE和position = "left",避免在分栏内过宽。
  • 间距优化:添加\vspace调整元素间距,提升排版美观度。

内容的提问来源于stack exchange,提问作者carolinasc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:10:56