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

为何含ggplot的R条件编译代码无法生成tikz图形?

问题背景

我用命令R -f figures.R运行脚本(从未使用RStudio),想实现仅重新生成已删除的论文图形,但碰到了怪事:

  • 套在if语句里的ggplot代码,生成的.tex文件只有两行注释;把if去掉后,代码又能正常生成完整图形文件。
  • 另一段用基础绘图函数(非ggplot)的相似代码,放在if里却能正常工作。

出问题的ggplot代码

figure <- '../paper/figures/recall_by_choices.tex'
if (!file.exists(figure)) {
    tikz(file=figure,width=3.5, height=2)
    mem1percent <- mem |>
        group_by(choices, success1) |>
        summarize(count=n()) |>
        mutate(Percent = count/sum(count) * 100)
    mem1percent |>
        ggplot(aes(x=factor(choices), y=Percent, fill=success1)) +
        geom_bar(stat='identity', position=position_dodge(), color='black') +
        labs(x="Choices", fill="7-day Recall") +
        scale_fill_manual(values=c('black','grey'))
    dev.off()
}

能正常运行的基础绘图代码

figure <- '../paper/figures/hmn_density.tex'
if (!file.exists(figure)) {
    tikz(file=figure,width=7, height=4)
    hmn <- table(ifelse(surveys$how_many == 'own' | surveys$how_many == 'n/a' | surveys$how_many == 'lots' | surveys$how_many == '', NA, ifelse(surveys$how_many == 'inf' | nchar(surveys$how_many) > 5, 100000, as.numeric(surveys$how_many))))
    plot(density(hmn), main='', xlab='Number of Choices')
    dev.off()
}

运行时的警告信息

当if条件成立时,两段代码分别输出:

summarise() has grouped output by 'choices'. You can override using the .groups argument.
null device
1

null device
1
Warning message:
In ifelse(surveys$how_many == "inf" | nchar(surveys$how_many) > :
NAs introduced by coercion


问题原因与解决办法

核心问题:ggplot的惰性渲染逻辑

ggplot和基础绘图函数的渲染机制完全不同:

  • 基础绘图函数(比如plot())是即时渲染,调用后直接把图形输出到当前打开的设备(这里是tikz创建的tex文件)。
  • ggplot是惰性求值:你写的ggplot代码只是创建了一个图形对象,并没有立刻把它画出来。在R控制台这种交互式环境里,这个对象会自动被打印渲染,但在if语句块这种非顶层代码环境中,R不会自动执行打印操作,所以图形根本没被输出到tikz设备里,最后dev.off()关闭设备时,只有空的注释内容被写入文件。

而去掉if语句后,ggplot对象处于顶层代码,R会自动打印它,所以能正常生成图形。

解决办法:显式打印ggplot对象

在if语句块里,手动调用print()来渲染ggplot对象即可,另外可以给summarize()加个参数消除分组警告:

figure <- '../paper/figures/recall_by_choices.tex'
if (!file.exists(figure)) {
    tikz(file=figure,width=3.5, height=2)
    mem1percent <- mem |>
        group_by(choices, success1) |>
        summarize(count=n(), .groups = "drop")  # 消除summarise的分组警告
    p <- mem1percent |>
        ggplot(aes(x=factor(choices), y=Percent, fill=success1)) +
        geom_bar(stat='identity', position=position_dodge(), color='black') +
        labs(x="Choices", fill="7-day Recall") +
        scale_fill_manual(values=c('black','grey'))
    print(p)  # 显式打印,让ggplot渲染到tikz设备
    dev.off()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:00:29