如何解决R Markdown文档中图表编号重复为Figure 1的问题
图表编号重复问题的解决方案
问题根源
你遇到的所有图表都显示为「Figure 1」,核心原因是混合使用了R代码块生成图和LaTeX原生figure环境,两者的编号计数器不互通:
- R代码块生成的图由knitr自动管理编号,但你手动在
fig.cap里加\label会干扰自动编号逻辑; - 直接用LaTeX的
figure环境时,它使用的是LaTeX原生计数器,和knitr维护的计数器完全独立,导致编号重复。
修复方案
方案1:统一用knitr管理所有图表(推荐)
把TikZ代码也放到R代码块中,让knitr统一处理编号、标题和交叉引用,彻底避免计数器冲突。
修改后的完整代码:
--- title: "demo" author: output: pdf_document: number_sections: true keep_tex: yes fontsize: 12pt linestretch: 1.2 subparagraph: true geometry: margin=1in header-includes: - \usepackage{amsmath} - \usepackage{amsthm} - \usepackage{bbm} - \numberwithin{equation}{section} - \usepackage{makecell} - \usepackage{indentfirst} - \usepackage{geometry} - \usepackage{graphicx} - \usepackage{tikz} - \usepackage{cleveref} # 直接加载,不要用AtEndPreamble包裹 --- ```{r fig.align="center", fig.cap="Trends", label="figure4", warning=FALSE, echo=FALSE, message=FALSE} library(ggplot2) options(scipen=999) # 关闭科学计数法 theme_set(theme_bw()) data("midwest", package = "ggplot2") gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(subtitle="Area Vs Population", y="Population", x="Area", title="Scatterplot", caption = "Source: midwest") print(gg) # ggplot推荐用print输出,替代plot
library(datasets) data("AirPassengers") passengers <- AirPassengers plot(passengers)
knitr::asis_output(' \\tikzset{every picture/.style={line width=0.75pt}} \\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1] \\draw [fill={rgb, 255:red, 0; green, 0; blue, 0 } ,fill opacity=0.32 ] (66.5,28.97) -- (248.5,28.97) -- (248.5,137) -- (66.5,137) -- cycle ; \\draw [fill={rgb, 255:red, 0; green, 0; blue, 0 } ,fill opacity=0.25 ] (62.5,265.61) -- (250.25,265.61) -- (250.25,356.79) -- (62.5,356.79) -- cycle ; \\end{tikzpicture} ')
knitr::asis_output(' \\tikzset{every picture/.style={line width=0.75pt}} \\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1] \\draw [fill={rgb, 255:red, 0; green, 0; blue, 0 } ,fill opacity=0.32 ] (66.5,28.97) -- (248.5,28.97) -- (248.5,137) -- (66.5,137) -- cycle ; \\draw [fill={rgb, 255:red, 0; green, 0; blue, 0 } ,fill opacity=0.25 ] (62.5,265.61) -- (250.25,265.61) -- (250.25,356.79) -- (62.5,356.79) -- cycle ; \\end{tikzpicture} ')
查看 \cref{fig:figure1}, \cref{fig:figure2}, \cref{fig:figure3} 和 \cref{fig:figure4}.
#### 关键修改说明: - 移除`fig.cap`里手动添加的`\label`,改用R代码块的`label`参数指定标签,knitr会自动生成正确的编号和交叉引用标记; - 用`knitr::asis_output()`把TikZ代码嵌入R代码块,让knitr统一处理图表环境; - 把`cleveref`从`\AtEndPreamble`中移出,直接加载,避免和knitr的自动编号逻辑冲突; - ggplot图改用`print(gg)`输出,确保符合ggplot的输出规范。 --- ### 方案2:同步LaTeX与knitr的计数器 如果坚持使用LaTeX原生`figure`环境,可通过修改LaTeX计数器实现编号统一: 在YAML的`header-includes`中添加以下代码,让LaTeX的`figure`计数器复用knitr的`plot`计数器: ```latex - \makeatletter - \let\c@figure\c@plot - \makeatother
同时修改所有R代码块的fig.cap,删除手动添加的\label,改用label参数指定标签(同方案1的R代码块写法)。
验证效果
编译后所有图表会按出现顺序依次编号为Figure 1到Figure 4,交叉引用也能正确指向对应图表。
内容的提问来源于stack exchange,提问作者jck21
相关产品推荐
相关产品推荐

