引题如果你的代码是这样的pdf(figure1_PCA3.pdf, width 3.5, height 3) biplot(p, x PC1, y PC2, colby Group, shape Group) dev.off()那么你的pdf文件将会显示文件损坏无法打开。那么我们该怎么样让他可以正常打开呢很简单pdf(figure1_PCA3.pdf, width 3.5, height 3) p1 - biplot(p, x PC1, y PC2, colby Group, shape Group) print(p1) dev.off()这样你就可以打开你的pdf文件了。同样的绘图函数同样的参数仅仅是加了一行print(p1)损坏的PDF就变正常了。这不是巧合更不是R的bug。这是你对R的图形系统理解还不够深。核心原因ggplot2是“懒”的biplot()函数来自PCAtools包。这个函数返回的对象不是一张画好的图而是一个包含所有绘图指令的ggplot对象。关键在于当你直接在一个函数调用后面不加print()时R的行为取决于运行环境。在R交互式环境命令行/RStudio控制台中biplot(p, x PC1, y PC2) # 自动打印图会显示R会自动调用print()所以你能看到图。在脚本中或pdf()设备内部pdf(output.pdf) biplot(p, x PC1, y PC2) # 不会自动打印 dev.off()R不会自动打印。 图形设备打开了但没有任何内容被“画”进去。你只是创建了一个ggplot对象然后丢弃了它。PDF文件虽然被创建但里面是空的——这就是你看到的“损坏文件”。print(p1)做了什么p1 - biplot(...) # 创建ggplot对象存到p1 print(p1) # 主动告诉R把这个图画到当前设备上print()函数会触发ggplot对象的渲染把图形真正“绘制”到当前打开的PDF设备中。有了内容PDF文件自然就是完整的、可打开的。为什么有时候不加print()也能成功这是因为某些绘图函数内部已经包含了print()或类似机制。例如基础R的plot()、hist()等函数它们直接向设备输出图形不返回需要打印的对象。ggplot2体系的设计哲学不同它分离了“创建图形对象”和“渲染图形”两个步骤。这种设计让你可以在创建对象后继续修改它比如加 theme_light()最后统一渲染。但这种设计的代价就是在非交互式环境中你必须显式调用print()。一句话记住在脚本中写ggplot2代码保存对象然后用print()或ggsave()输出。不要依赖自动打印。这不是R的缺陷而是ggplot2设计上的取舍。理解了这一点你就再也不会被“PDF损坏”困扰了。云生信团队简介“ 云生信” 团队致力于为生命科学领域研究者提供专业的生物信息学服务 主营业务包括 定制生信分析、生信云服务器租赁及托管、生信课程、算法开发、数据挖掘、数据库开发 等服务。 团队打造的“ 云生信” 自动化分析平台 是国内首个标准化分析个性化分析的开放型生物信息学在线平台。http://www.biocloudservice.com/ 目前“ 云生信” 团队已获得40余项独立软件著作权证书 还有3项发明专利。服务领域定制分析业务 根据客户需求 订制个性化数据分析。 包含自有测序数据高级分析、公共 数据库挖掘分析 整合分析等 热点涵盖 机器学习、单细胞测序、孟德尔随机化、 网络 药理学、 GBD等临床数据库挖掘分析、分子对接及分子动力学模拟等......生信云服务器 超十年服务器深度操作经验 提供卓越服务器租赁与托管服务。 用户享受一对一技术支持软件安装、环境搭建等近20P规模服务获众多客户续费与推荐。生信课程 专注生信、 专注实操 内容涵盖单细胞、 空转、 MR等热点方向以及机器学习等 前沿技术重点讲解 热点全面 持续更新生信前沿热点。感兴趣的老师可以扫描下方二维码联系我们哦!!