ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

R语言绘图中文字符显示问题全解析:从字体渲染到跨平台解决方案

R语言绘图中文字符显示问题全解析:从字体渲染到跨平台解决方案 1. 从豆腐块说起R语言绘图中文字符失效的真实困境如果你用R画图时遇到过坐标轴刻度、图例或者标题里的中文变成一个个空心方框、乱码甚至直接消失那这篇文章就是写给你看的。这个问题几乎每个用R做过数据可视化的中文用户都会撞上Windows、macOS、Linux三大平台无一幸免区别只是死法不同。先说结论R本身完全支持中文字符问题出在图形设备Graphics Device对中文字体的渲染链路上。R默认的绘图设备在不同操作系统下会调用不同的底层字体处理机制一旦字体加载失败或匹配不到合适的中文字形就会退化成占位符——也就是你看到的豆腐块。我最早踩这个坑是在做一份供应链数据分析报告需要用ggplot2画一组分地区的销售热力图结果地区名称全部变成方框。当时第一反应是数据编码问题折腾了半天才意识到是字体渲染的问题。后来陆续在RStudio、R Markdown、Shiny应用里反复遇到类似情况算是把这个问题的各种变种摸了个遍。这篇文章会从底层原因讲起然后分平台、分场景给出可复现的解决方案包括基础绘图、ggplot2、R Markdown导出PDF、Shiny动态图表等不同场景下的处理方式。最后把我这些年积累的排查思路和坑点一并整理出来希望能帮你少走弯路。2. 中文不显示的底层机制R绘图设备与字体渲染链路拆解2.1 图形设备的差异是问题的第一根源R的绘图操作最终都要交付给某个图形设备来执行。不同设备的字体处理能力差异非常大这是中文不显示最核心的底层原因。Windows下的默认设备Windows()基于GDIGraphics Device Interface绘制理论上支持系统已安装的所有字体。但它有一个隐含的坑——对字体名称的大小写和精确匹配很敏感而且默认字体Arial不包含中文字形需要R自行完成字体回退Font Fallback才能在Arial缺失时调用系统中文字体。早期版本的R在Windows设备上字体回退机制不完善导致中文直接失效。macOS下的默认设备quartz()基于Core Graphics框架字体渲染能力较强对中文字体支持相对好一些。但quartz设备默认使用的字体家族如果指定为Helvetica或Arial同样会触发中文字形缺失问题。Linux下的默认设备X11()依赖系统安装的字体服务fontconfig如果系统没装中文字体或者R的字体配置没有正确关联到fontconfig结果就是彻底的空缺。PDF设备pdf()PDF设备在做文本绘制时会嵌入字体但它对中文的支持取决于系统能否提供合适的中文字体文件。如果系统里只有点阵中文字体或者字体嵌入出现编码映射错误导出的PDF里中文就会变成乱码。2.2 字体家族匹配与字形缺失的连锁反应R在绘制文本时会逐级匹配字体家族Font Family。当你用familyserif或familysans指定字体时R会在当前设备的字体表中查找对应的实际字体文件。问题出在中文字符在ASCII字体的字形表中根本不存在。举个直观的例子Arial字体文件里只有拉丁字母、数字和符号的字形描述没有供应链三个汉字的字形。R拿到供应链这个字符串去Arial字体文件里找字形找不到正常情况下应该回退到系统中文字体但在某些设备或旧版本R中回退失败就直接渲染成空框或空白。这就像你去一家只卖西餐的餐厅点了一碗阳春面厨房做不出来又不告诉你端上来一盘空盘子。2.3 编码问题另一个被误判的中文不显示除了字体问题还有一类情况是数据本身的编码问题尤其是从外部导入的中文数据。如果你的CSV文件是GBK编码而R读取时按UTF-8解析中文字符就已经变成乱码了——这属于数据层面出了问题并不是绘图设备的锅。区分这两类问题有一个很简单的办法在R控制台里直接print(你的中文字符串)如果控制台输出正常说明数据编码没问题问题出在绘图设备如果控制台本身就是乱码那得先解决数据读取编码。2.4 一个直观的实验用不同设备绘制中文看差异为了让你直观理解设备差异我写了一段测试代码分别在Windows设备、PDF设备和Cairo设备上绘制同一段中文文本# 中文测试文本 test_label - 供应链数据分析报告华东区 # 先在屏幕上画 windows() plot(1, 1, type n, xlab , ylab ) text(1, 1, labels test_label, cex 2) # 存成PDF看看 pdf(test_cn.pdf, width 6, height 4) plot(1, 1, type n, xlab , ylab ) text(1, 1, labels test_label, cex 2) dev.off() # 用Cairo设备再存一次 library(Cairo) CairoPDF(test_cn_cairo.pdf, width 6, height 4) plot(1, 1, type n, xlab , ylab ) text(1, 1, labels test_label, cex 2) dev.off()如果你在Windows上运行这段代码大概率第一个windows()窗口里中文正常PDF设备可能正常也可能乱码取决于系统字体Cairo设备基本都能正常。这就是设备差异最直接的体现。3. 第一套方案通过字体配置从根源解决问题3.1 明确你的系统有哪些中文字体在动手配置之前先搞清楚系统里有哪些中文字体可以用。不同平台查字体的方式不同。Windows下打开设置-个性化-字体或者在命令行执行fc-list :langzh如果提示fc-list不是内部或外部命令说明系统没有fontconfig工具Windows用户不需要特别安装直接在R里用windowsFonts()查看R能识别的字体列表即可。macOS下在终端执行fc-list :langzh # 或者 system_profiler SPFontsDataType | grep -i 中文\|SC\|TCLinux以Ubuntu为例下fc-list :langzh如果没有输出说明系统没装中文字体需要先安装sudo apt install fonts-noto-cjk3.2 Windows平台的字体注册与指定Windows下最直接的方式是用windowsFonts()注册中文字体然后在绘图时通过family参数引用# 查看当前可用的字体 windowsFonts() # 注册中文字体 windowsFonts(CN windowsFont(Microsoft YaHei)) # 在基础绘图里使用 plot(1:10, main 标题测试, family CN) # 在ggplot2里使用 library(ggplot2) ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文标题测试) theme(text element_text(family CN))微软雅黑Microsoft YaHei是Windows系统自带的中文字体覆盖范围广渲染效果清晰。如果你更习惯宋体或黑体可以换成SimSun或SimHei。这里有一个细节容易踩坑windowsFonts()注册的字体名不能带空格实际上可以带但引用时必须带引号。比如注册windowsFonts(CN windowsFont(Microsoft YaHei))使用family CN就对了不需要再写全名。3.3 使用showtext包跨平台的统一解决方案如果你不想在不同操作系统上分别折腾字体配置我强烈推荐showtext包。它的原理是绕过R默认的字体渲染机制直接把字体文件加载进来用软件渲染的方式把文本绘制到图形设备上从根源规避设备间差异。library(showtext) # 加载中文字体 font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) # Windows # font_add(my_cn, regular /System/Library/Fonts/PingFang.ttc) # macOS # font_add(my_cn, regular /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc) # Linux # 启用showtext showtext_auto() # 正常绘图 library(ggplot2) ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文标题测试) theme(text element_text(family my_cn))showtext_auto()只需要调用一次之后所有绘图设备包括PDF、PNG、屏幕都会自动使用showtext的文本书写引擎。这个包兼容性极好我在Windows 10、macOS 12、Ubuntu 20.04上都实测过没有遇到过失败的情况。需要注意的坑showtext_auto()的高分辨率问题。如果你在RStudio里缩放绘图窗口文本偶尔会显得模糊——这是因为showtext的软件渲染基于固定的dpi计算。解决办法是在showtext_auto(enable TRUE)之后再次调用showtext_begin()和showtext_end()包裹具体绘图代码强制重新计算。3.4 用extrafont包将系统字体纳入R的字体表另一个老牌方案是extrafont包它的思路是把系统已安装的字体注册到R的字体数据库中让R能在绘图时找到它们。# 安装并加载 install.packages(extrafont) library(extrafont) # 导入系统字体只需要执行一次 font_import(pattern YaHei|SimHei|SimSun|Noto) # 查看导入的字体 fonts() # 注册到Windows设备 loadfonts(device win) # loadfonts(device pdf) # 如果要导出PDF使用方式ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文标题测试) theme(text element_text(family Microsoft YaHei))extrafont的优势是字体管理更系统化适合需要频繁切换字体、或者需要把字体信息嵌入PDF的场景。但它有一个明显的问题font_import()首次运行时非常慢因为要扫描系统全部字体文件并建立映射此外在Linux上需要确保fontconfig库完整否则loadfonts()会报错。4. 第二套方案不同绘图场景下的专项处理4.1 基础绘图base plot的中文显示基础绘图函数plot()、text()、title()等处理中文相对简单有两条路可以走第一条路是设置全局参数一次性解决后续所有基础绘图的字体问题# Windows下 par(family Microsoft YaHei) plot(1:10, main 中文标题, xlab 横轴, ylab 纵轴)第二条路是用showtext配合全局字体设置library(showtext) font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() par(family my_cn) plot(1:10, main 中文标题, xlab 横轴, ylab 纵轴)基础绘图里还有一类特殊情况legend()函数中的中文。有时主标题和坐标轴都能正常显示但图例里的中文变方框。这是因为legend()对字体参数的处理机制不同需要在legend()内部单独指定family参数plot(1:10, type n) legend(topright, legend c(实验组, 对照组), fill c(red, blue), family Microsoft YaHei)4.2 ggplot2体系下的字体统一配置ggplot2的中文问题集中在theme()函数的字体配置上。我的习惯是先用theme_set()全局统一主题避免每张图重复写library(ggplot2) # 方案A使用windowsFonts注册的字体 windowsFonts(CN windowsFont(Microsoft YaHei)) theme_set(theme_gray(base_family CN)) # 方案B配合showtext library(showtext) font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() theme_set(theme_gray(base_family my_cn)) # 之后画的所有图都自动使用中文字体 ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 回归分析重量与油耗关系, x 车辆重量千磅, y 每加仑行驶里程)如果你只需要在单独一张图里临时修改字体可以局部覆盖theme设置ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文标题) theme(text element_text(family my_cn, size 14), plot.title element_text(family my_cn, face bold))值得一提的是ggrepel包的文字标签。ggrepel常用在散点图上标注数据点它的标签文本同样受family参数控制。但有一个隐藏坑geom_text_repel()对字体的处理依赖grid图形系统在某些设备上会出现标签中文正常、但点周围的斥力区域出现乱码方块的怪现象。解决方式依然是showtext兜底或者改用geom_text()配合避让算法。4.3 R Markdown/Quarto导出PDF时中文字体嵌入这可能是最让人头秃的场景——在RStudio里看到的图形一切正常但渲染成PDF报告后中文全部消失。原因是R Markdown渲染PDF时走的是LaTeX引擎默认是pdflatex或xelatexLaTeX默认字体Computer Modern里根本没有中文字形。解决方案一在YAML配置中指定CJK主字体xelatex方案--- title: 中文报告 output: pdf_document: latex_engine: xelatex extra_dependencies: - ctex keep_tex: true ---这个方案依赖LaTeX发行版里的ctex宏包和系统中文字体。需要确保你的TeX环境完整MacTeX/TeX Live建议完整安装不要用精简版。解决方案二提前把图表导出为图片再插入如果你对LaTeX不熟悉最简单粗暴的方式是让R Markdown不直接渲染R图表而是先通过代码块生成PNG图片再通过knitr::include_graphics()插入{r plot-chunk, echoFALSE, fig.cap中文图表} library(ggplot2) library(showtext) font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() p - ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文图表) theme(text element_text(family my_cn)) ggsave(plot_cn.png, p, width 6, height 4, dpi 300) knitr::include_graphics(plot_cn.png) 解决方案三用Cairo设备渲染PDF如果你一定要在PDF里保留矢量格式可以使用Cairo的PDF设备cairo_pdf(output.pdf, width 6, height 4) ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 中文图表) theme(text element_text(family Microsoft YaHei)) dev.off()cairo_pdf()会调用Cairo图形库它在字体处理和文本布局上远强于R内置的PDF设备能比较好地处理中文字体嵌入。4.4 Shiny应用中的中文显示与浏览器字体关系Shiny应用里图表的渲染路径和本地绘图完全不同。Shiny通过WebSocket把绘图指令发送给浏览器最终由浏览器的HTML渲染引擎负责画图。这意味着字体能否正常显示取决于浏览器端能不能匹配到合适的中文字体而不是R环境。所以在Shiny应用里R代码层面能做的有限主要是确保传给浏览器的图表中family参数指向一个浏览器能识别的字体家族名# 在Shiny里用通用字体族更稳妥 theme(text element_text(family sans)) # 或者直接指定浏览器常见中文字体 theme(text element_text(family Microsoft YaHei))另外一个容易被忽视的点Shiny的renderPlot()输出PNG图片时R端会先通过设备把图形画成图片再发给浏览器。这一步还是会走R的图形设备所以本地绘图的那一套配置依然需要。只有在使用renderPlotly()、renderEcharts4r()等基于JavaScript的交互式图表库时字体才完全由浏览器端控制。5. 实测记录Windows、macOS、Linux三平台中文显示修复验证5.1 Windows 11环境实测测试环境Windows 11 专业版、R 4.3.1、RStudio 2023.09。直接使用内置默认设置时plot()函数的中文标题在屏幕窗口正常显示但导出PNG时标题变成一排方框。这个现象在旧版本R中更明显新版本R4.2已经改善了不少。按以下步骤修复后屏幕和文件导出均正常library(showtext) font_add(yahei, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() # 测试 png(test_win.png, width 800, height 600, res 150) ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title Windows平台中文测试) dev.off()实测结论showtext在Windows上表现最稳定几乎没有兼容性问题。唯一需要注意的是如果你用了RStudio内置的Export按钮导出图片可能会绕过showtext的渲染管线导致导出的图片仍无中文。建议统一使用ggsave()或png()dev.off()代码方式导出。5.2 macOS环境实测测试环境macOS 13 Ventura、R 4.3.1、RStudio 2023.09。macOS的quartz设备对中文支持不错直接画屏幕图通常没问题。但使用ggsave()导出PNG时如果未指定设备R会默认使用png()设备这时中文可能丢失。修复方案library(showtext) font_add(pingfang, regular /System/Library/Fonts/PingFang.ttc) showtext_auto() ggsave(test_mac.png, width 6, height 4, dpi 300)实测结论macOS上PingFang.ttc是系统默认中文字体路径固定使用方便。但有个细节——RStudio的Graphics窗口在macOS上默认使用quartz设备如果你用showtext_auto()但没指定其他设备RStudio内部的显示可能正常但一旦ggsave()导出就要重新走一遍字体配置。建议在RProfile里统一设置全局showtext参数。5.3 LinuxUbuntu环境实测测试环境Ubuntu 22.04 LTS、R 4.3.1、无桌面环境纯命令行。Linux下最容易出问题因为很多服务器版系统默认没有中文字体。先检查fc-list :langzh如果输出为空安装字体sudo apt update sudo apt install fonts-noto-cjk然后在R里配置library(showtext) font_add(noto, regular /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc) showtext_auto() ggsave(test_linux.png, width 6, height 4, dpi 300)实测结论Ubuntu装好Noto CJK字体后配合showtext一切正常。如果你不想要showtext这个依赖直接用png()设备并指定family Noto Sans CJK SC也可以png(test_linux2.png, width 800, height 600, res 150) par(family Noto Sans CJK SC) plot(1:10, main Linux中文测试) dev.off()5.4 三平台方案对比总结平台内置字体推荐方案注意事项Windows微软雅黑、宋体、黑体showtext msyh.ttcRStudio导出按钮可能绕过showtext用代码导出macOS苹方、冬青黑体、宋体showtext PingFang.ttc注意ttc文件路径无需额外安装字体Linux取决于安装情况先装fonts-noto-cjk再showtext无中文字体时一切配置都白搭6. 特殊场景与进阶技巧生僻字、批量导出与字体嵌入6.1 生僻字和特殊符号的显示问题常规中文字体覆盖的字形范围有限如果你的数据中包含生僻字比如龘爨或者需要显示特殊符号如㏄№普通中文字体可能无法渲染。这时有两个方向一是使用更全的字体。思源宋体/黑体Source Han Serif/Sans的字符覆盖范围极广基本能覆盖所有生僻汉字。下载后注册给R即可font_add(sourcehan, regular C:/Users/你的用户名/Downloads/SourceHanSansSC-Regular.otf) showtext_auto()二是使用cwhmisc或unicode文本转义。R支持Unicode转义序列可以用\u加十六进制编码表示任意字符。先用utf8ToInt()查出字符编码再手动输入转义序列# 龘 的Unicode编码是 U9F98 label - \u9F98 text(1, 1, labels label, family my_cn)这个方法的适用场景是字符本身没问题、但数据源在传输过程中编码损坏。比如从Excel导入时遇到编码异常U转义可以绕过中间环节的编码转换问题。但如果字体本身没有这个字形转义也没用。6.2 循环批量导出大量图表时的字体踩坑做数据分析报告时我经常需要循环生成几十张图表。这时容易遇到一个问题在循环里反复调用showtext_auto()或者切换字体会导致部分图表字体失效。我的建议是字体配置只做一次放在循环体外library(showtext) font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() for (region in regions) { p - ggplot(data_filtered, aes(x, y)) geom_point() labs(title paste0(region, 销售趋势)) theme(text element_text(family my_cn)) ggsave(paste0(chart_, region, .png), p, width 8, height 6, dpi 200) }另外ggsave()在保存时会根据文件扩展名自动选择图形设备PNG文件会走png()设备。如果你同时使用了showtext请确保showtext_auto()已经开启否则PNG输出仍然会丢中文。6.3 把中文字体嵌入PDF供印刷使用印刷场景要求PDF里的文字是矢量可编辑的这比屏幕显示要求更高。用cairo_pdf()设备保存ggplot2图表可以确保中文字体作为矢量轮廓嵌入library(ggplot2) library(showtext) font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) showtext_auto() cairo_pdf(print_ready.pdf, width 6, height 4) ggplot(mtcars, aes(wt, mpg)) geom_point() labs(title 印刷版中文图表) theme(text element_text(family my_cn)) dev.off()检查PDF是否成功嵌入字体可以用pdffonts命令Linux/macOS自带pdffonts print_ready.pdf输出结果里应该能看到中文字体名称如MicrosoftYaHei、NotoSansCJK而不是Identity-H编码的匿名子集——后一种情况通常意味着字体信息在嵌入过程中丢失了。7. 故障排查思路当所有方案都不生效时的定位路径7.1 用系统工具确认问题出在R还是系统层有些情况下你配置了字体R也没有报错但中文就是显示不出来。这时需要系统性地排查而不是继续乱试方案。我先分清楚问题的层次字符能不能在R控制台正常输出不能——数据编码问题先修数据读取。字符在屏幕设备能显示、导出文件不能字体配置只覆盖了部分设备用showtext统一。导出PNG正常、导出PDF不行PDF设备字体嵌入机制特殊改用cairo_pdf。所有设备都不行检查系统字体是否安装、字体路径是否正确。7.2 fontconfig工具排查Linux字体配置在Linux上排查字体问题fc-list是核心工具# 查看所有中文字体 fc-list :langzh # 查看某个具体家族的全部样式 fc-list | grep -i noto # 刷新字体缓存 fc-cache -fv如果R里报font family not found但fc-list显示字体确实存在可能是R的fontconfig绑定没有正确读取缓存。尝试重启R进程或者在~/.Rprofile里加上# 强制重新加载fontconfig配置 Sys.setenv(FC_DEBUG 1024)设置这个环境变量后重新运行R会在控制台输出详细的字体解析日志能直观看到R在解析family参数时匹配到了哪个字体文件。7.3 Windows下字体被策略锁定导致渲染失败Windows系统偶尔会遇到字体已安装但无法被R调用的怪事。原因可能是字体文件被系统策略锁定尤其是企业管理的电脑或者字体文件损坏。排查步骤确认字体能正常使用打开Word或其他应用看能否选择该字体。检查字体文件路径权限R进程需要有权限读取字体文件如果RStudio是管理员权限运行而字体文件在用户目录下可能出现权限不匹配。用file.exists(C:/Windows/Fonts/msyh.ttc)在R里确认文件是否可访问。还有一个零成本的办法换一个字体试试。微软雅黑出问题时试试黑体simhei.ttf或宋体simsun.ttc往往能绕过特定字体文件的渲染故障。7.4 我总结的中文不显示三步定位法根据多年实战我总结出了一套定位流程基本能覆盖99%的情况第一步控制台打印。运行print(中文)确认数据本身没问题。第二步换设备测试。用png()、cairo_pdf()、pdf()分别试一遍看是普遍失败还是特定设备失败。这一步能快速缩小问题范围。第三步换方案测试。如果普遍失败用showtext一次性兜底解决如果是特定设备失败针对该设备配置专用方案如PDF用cairo_pdf。多数情况下这个流程走完问题就能解决。8. 从画图前就开始防坑数据准备与输出环境的一体化思路聊完具体的解决方案我想再从项目实战的角度聊几个容易被忽略的预防性操作。8.1 数据读取阶段就锁定编码问题很多中文不显示问题追根溯源是数据读取时编码就乱了。R 4.0之后read.csv()默认使用UTF-8编码读取如果你处理的是GBK编码的老旧Excel导出文件中文字符必然变成乱码。一个稳妥的习惯是读取外部数据时显式指定编码# Windows下常见GBK df - read.csv(data.csv, fileEncoding GBK) # 或统一转码 df - read.csv(data.csv, fileEncoding UTF-8) df$列名 - iconv(df$列名, from GBK, to UTF-8)进场时就把编码问题解决掉后面画图才不会反复踩坑。8.2 用RProfile统一配置防止新项目重蹈覆辙如果你发现自己经常要处理中文图表强烈建议在~/.Rprofile里做全局配置一劳永逸# ~/.Rprofile if (interactive()) { library(showtext) # 根据操作系统自动选择中文字体路径 if (.Platform$OS.type windows) { font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) } else if (Sys.info()[sysname] Darwin) { font_add(my_cn, regular /System/Library/Fonts/PingFang.ttc) } else { font_add(my_cn, regular /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc) } showtext_auto() # 设置ggplot2全局主题 ggplot2::theme_set( ggplot2::theme_gray(base_family my_cn) ) }这样每次启动RStudio中文字体配置自动生效新项目直接画图不折腾。8.3 团队协作时把字体方案写进README如果你在团队里共享R脚本或者做代码交付建议在项目README里明确写好字体配置要求。我自己就遇到过合作方在macOS上跑Windows写的脚本结果因为字体路径不同生成图表全部乱码。在README里加一段简要说明成本极低回报极高## 中文图表依赖 - Windows: 无需额外安装脚本自动调用微软雅黑 - macOS: 使用系统自带苹方字体 - Linux: 需安装 fonts-noto-cjksudo apt install fonts-noto-cjk - 统一使用showtext包渲染中文脚本会自动检测系统类型加载对应字体9. 这些年我在中文画图上踩过的几个隐蔽坑9.1 RStudio的Export按钮并不总是可靠有一类问题非常隐蔽RStudio绘图窗口明明显示中文正常但点Export按钮保存的图片却没有中文。这背后的原因是RStudio绘图窗口和导出功能走的是不同的图形设备路径导出时不会完整继承绘图窗口的字体渲染设置。我现在的习惯是任何需要交付的图表一律用代码导出ggsave()或png()dev.off()不用RStudio的手动导出功能。这样保证图表输出效果和代码效果一致而且可复现。9.2 ttc与ttf字体文件格式的区别Windows系统的微软雅黑是.ttc格式TrueType Collection一个文件里包含多个字体Regular、Bold、Light。大部分情况下showtext和extrafont都能正确处理.ttc文件但个别旧版本包对.ttc支持不完整。如果你发现用.ttc文件报错或字体注册失败可以试试注册font_add()时指定index参数font_add(yahei, regular C:/Windows/Fonts/msyh.ttc, index 1)index 1对应.ttc文件里的第二个字体通常是Bold或Light。如果.ttc始终有问题也可以用系统自带的单字体.ttf文件比如黑体的simhei.ttf。9.3 缩放和分辨率不同导致的中文模糊有些场景下中文能显示但文字边缘发虚、整体模糊。这通常不是字体缺失而是渲染精度问题。屏幕显示用的dpi96左右和出版印刷用dpi300对文字清晰度影响巨大。在ggsave()里调高dpi参数ggsave(high_res.png, p, width 6, height 4, dpi 300)如果导出的是矢量格式就不存在这个问题PDF和SVG都是矢量格式放大多大都不会变模糊。9.4 环境变量LANG和LC_ALL对R中文字符处理的影响在Linux服务器上跑R脚本时如果系统的locale设置不包含UTF-8R可能无法正确处理中文字符串。这个问题的表现是数据读取正常、控制台打印正常但绘图时中文字符被截断或替换成空串。检查当前localeSys.getlocale()如果输出的是C或POSIX需要设置UTF-8export LANGen_US.UTF-8 export LC_ALLen_US.UTF-8或者直接在R脚本开头加Sys.setlocale(LC_ALL, en_US.UTF-8)有朋友跟我说每次都要手动设置很麻烦可以追加到系统的~/.bashrc或.Renviron文件里一劳永逸。10. 最优实践我目前固定使用的中文画图配置方案如果让我推荐一套拿来即用、跨平台无脑复制的方案我会选showtext 通用字体配置 代码导出这套组合。# ---- 全局配置脚本font_setup.R ---- library(showtext) library(ggplot2) # 检测系统并加载合适的中文字体 setup_cn_font - function() { if (.Platform$OS.type windows) { font_add(my_cn, regular C:/Windows/Fonts/msyh.ttc) } else if (Sys.info()[sysname] Darwin) { font_add(my_cn, regular /System/Library/Fonts/PingFang.ttc) } else { font_add(my_cn, regular /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc) } showtext_auto() } setup_cn_font() # 全局主题指定中文字体 theme_set(theme_gray(base_family my_cn))每次新建分析项目只需要source(font_setup.R)一次后续所有图表自动支持中文。如果遇到个别图表需要特殊字体再局部覆盖即可。这套配置的好处是底层原理统一showtext的软件渲染绕过了所有设备差异代码可移植Windows/macOS/Linux通用对ggplot2、基础绘图、R Markdown全部生效不容易被R版本更新破坏如果你不想引入任何第三方包只想用R自带功能解决那么Windows平台最简方案是windowsFonts(CN windowsFont(Microsoft YaHei)) par(family CN)macOS和Linux下R自带的解决方案相对有限建议不要折腾直接上showtext。最后再说一个实用习惯画完图后我总会把dev.off()前的图形检查一遍特别是看标题、图例、坐标轴是否有中文字符缺失。这个检查几乎是肌肉记忆了——因为中文显示问题太常见而且同一个脚本在不同操作系统上表现常常不同。如果你和我一样经常换电脑办公把showtext方案固定下来能省下大量无意义的排障时间。
返回列表