在R語言環(huán)境中,畫圖有兩種情況,一是直接用R自帶的繪圖功能,也就是默認(rèn)的
plot函數(shù)。還一種是用第三方繪圖包,例如ggplot2和lattice這樣的繪圖包,要在這兩種情況下都能正常顯示中文,操作方式是不一樣的。
我的操作系統(tǒng)是macOS 10.13.6,R語言安裝的是3.6.1版本,從網(wǎng)上下載了免費(fèi)的思源黑體和更紗黑體(Sarasa Mono)字體文件,下面以此為基礎(chǔ)說一下操作步驟::
解決plot的亂碼問題
- 確定在
$HOME目錄中有.Rprofile文件,如果你的系統(tǒng)中沒有,可以用
touch ~/.Rprofile
的方法建立一個(gè)空白的配置文件。
- 用編輯器打開
.Rprofile,輸入如下配置信息:
# My profile file
# 設(shè)置繪圖設(shè)備的屬性Hook函數(shù),在繪圖設(shè)備啟動(dòng)的時(shí)候自動(dòng)載入
setHook(packageEvent("grDevices", "onLoad"),
function(...) {
WIDTH = 7; HEIGHT = 5.25; POINT_SIZE=10;
# macOS Quartz
grDevices::quartz.options(
width = WIDTH,
height = HEIGHT,
pointsize = POINT_SIZE,
dpi = 96)
styles = c("-Light", "-Regular", "-Medium", "-Bold")
styles2 = c("-Regular", "-Bold", "-Italic", "-Bold-Italic")
grDevices::quartzFonts(
serif=grDevices::quartzFont(paste0("SourceHanSerif", styles)),
sans=grDevices::quartzFont(paste0("SourceHanSans", styles)),
mono=grDevices::quartzFont(paste0("Sarasa-Mono-CL", styles2)) )
# PDF Output
grDevices::pdf.options(
width = WIDTH,
height = HEIGHT,
pointsize = POINT_SIZE,
family = "GB1")
}
)
# 默認(rèn)調(diào)用plot的時(shí)候每次都需要設(shè)置中文字體,hook之后就簡(jiǎn)單了
setHook("before.plot.new",
function(...){
if(par('family') == '') par(family="mono");
},
'append'
)
這兩個(gè)hook函數(shù),一個(gè)是在Device加載的時(shí)候運(yùn)行,用于設(shè)置繪圖設(shè)備的長、寬、DPI等參數(shù),同時(shí)建立字體列表,我的是macOS系統(tǒng),在蘋果系統(tǒng)下繪圖設(shè)備是quartz,所以創(chuàng)建字體用quartzFonts函數(shù),如果你不是蘋果系統(tǒng),可以在R運(yùn)行環(huán)境下調(diào)用一次plot函數(shù)打開一個(gè)繪圖窗口,然后用dev.list()看看當(dāng)前設(shè)備名稱是什么,就知道對(duì)應(yīng)的函數(shù)名稱。
我建立了三個(gè)字體列表,分別是襯體(serif),無襯體(san)和等寬(mono),后續(xù)我只用這個(gè)mono字體,為什么?后面稍做解釋。
第二個(gè)hook函數(shù)在plot啟動(dòng)的時(shí)候運(yùn)行,網(wǎng)上還有一種方法,就是不用hook這個(gè)plot,在前一個(gè)hook函數(shù)中修改device的屬性,這個(gè)也可以,但是只能在R運(yùn)行環(huán)境中正常工作,RStudio中就無能為力,不如hook掉plot,這樣兩種運(yùn)行環(huán)境下都能正常工作。這個(gè)hook的作用就是檢查當(dāng)前有沒有設(shè)置字體,如果沒有就設(shè)置為mono字體,而前面我已經(jīng)建立了mono字體列表,實(shí)際上就是更紗黑體,所以這里就相當(dāng)于告訴plot,你有沒有特別指定字體啊,沒有的話就用更紗黑體吧。
- 測(cè)試結(jié)果,保存
.Rprofile并啟動(dòng)R,輸入
> plot(cos, -pi*2, pi*2, xlab='自變量', ylab='因變量',
main='一個(gè)余弦函數(shù)', font=3)
這里font=3的意思是用斜體,我前面說了一直用這個(gè)mono的更紗黑體,道理就在這里,一般中文字體文件中不含斜體,其實(shí)有時(shí)候我們還是需要斜體的西文字體,更紗黑體剛好有斜體,所以就用它了。結(jié)果如圖

至此,R語言的默認(rèn)中文繪圖環(huán)境已經(jīng)設(shè)置完畢,下面說一下第三方繪圖包中的亂碼問題
解決ggplot2的中文亂碼
ggplot2并沒有繼承基礎(chǔ)繪圖的配置,所以我們得給它單獨(dú)配置,不過也很簡(jiǎn)單,打開~/.Rprofile文件,再加一個(gè)hook函數(shù):
# 設(shè)置ggplot2使用中文字體
setHook(packageEvent("ggplot2", "attach"),
function(...) {
try({
theme_set(theme_get() +
theme(text=element_text(family='Sarasa Mono CL')))
})
}
)
是不是更簡(jiǎn)單?其實(shí)在繪圖當(dāng)中,我們也可以臨時(shí)設(shè)置字體,只是每次都設(shè)置有點(diǎn)麻煩,我這樣一次性設(shè)置之后使用起來就非常方便了。
保存配置文件之后再打開R運(yùn)行環(huán)境,輸入:
library(ggplot2)
qplot(1:10, rnorm(10), main='正太隨機(jī)抽取')
結(jié)果如下:

每個(gè)第三方包的工作方式都不一樣,這也就意味著每加入一個(gè)繪圖包,都可能要重新定義,例如lattice就是另外一直方式。
解決lattice的亂碼問題
lattice沒有ggplot2那么簡(jiǎn)單明了,實(shí)際上我在中文網(wǎng)站上竟然沒有發(fā)現(xiàn)有人知道如何設(shè)置!是的,它確實(shí)比較隱秘,但還是有辦法的:-),打開~/.Rprofile文件,加入如下hook函數(shù):
# 設(shè)置lattice使用中文
setHook(packageEvent("lattice", "attach"),
function(...) {
try({
font.settings <- list(fontfamily = "mono")
my.theme <- list(
add.text = font.settings,
axis.text = font.settings,
par.xlab.text = font.settings,
par.ylab.text = font.settings,
par.zlab.text = font.settings,
par.main.text = font.settings,
par.sub.txt = font.settings )
lattice.options(default.theme = my.theme)
})
}
)
好了,我們?cè)賮砜纯葱Ч绾危?/p>
library(lattice)
histogram(~mpg, mtcars, main='每加侖英里數(shù)')
