在R語言環(huán)境中,畫圖有兩種情況,一是直接用R自帶的繪圖功能,也就是默認的
plot
函數(shù)。還一種是用第三方繪圖包,例如ggplot2
和lattice
這樣的繪圖包,要在這兩種情況下都能正常顯示中文,操作方式是不一樣的。
我的操作系統(tǒng)是macOS 10.13.6,R語言安裝的是3.6.1版本,從網(wǎng)上下載了免費的思源黑體和更紗黑體(Sarasa Mono)字體文件,下面以此為基礎(chǔ)說一下操作步驟::
解決plot
的亂碼問題
- 確定在
$HOME
目錄中有.Rprofile
文件,如果你的系統(tǒng)中沒有,可以用
touch ~/.Rprofile
的方法建立一個空白的配置文件。
- 用編輯器打開
.Rprofile
,輸入如下配置信息:
# My profile file
# 設(shè)置繪圖設(shè)備的屬性Hook函數(shù),在繪圖設(shè)備啟動的時候自動載入
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")
}
)
# 默認調(diào)用plot的時候每次都需要設(shè)置中文字體,hook之后就簡單了
setHook("before.plot.new",
function(...){
if(par('family') == '') par(family="mono");
},
'append'
)
這兩個hook函數(shù),一個是在Device加載的時候運行,用于設(shè)置繪圖設(shè)備的長、寬、DPI等參數(shù),同時建立字體列表,我的是macOS系統(tǒng),在蘋果系統(tǒng)下繪圖設(shè)備是quartz
,所以創(chuàng)建字體用quartzFonts
函數(shù),如果你不是蘋果系統(tǒng),可以在R運行環(huán)境下調(diào)用一次plot函數(shù)打開一個繪圖窗口,然后用dev.list()
看看當(dāng)前設(shè)備名稱是什么,就知道對應(yīng)的函數(shù)名稱。
我建立了三個字體列表,分別是襯體(serif),無襯體(san)和等寬(mono),后續(xù)我只用這個mono字體,為什么?后面稍做解釋。
第二個hook函數(shù)在plot
啟動的時候運行,網(wǎng)上還有一種方法,就是不用hook這個plot
,在前一個hook函數(shù)中修改device的屬性,這個也可以,但是只能在R運行環(huán)境中正常工作,RStudio中就無能為力,不如hook掉plot
,這樣兩種運行環(huán)境下都能正常工作。這個hook的作用就是檢查當(dāng)前有沒有設(shè)置字體,如果沒有就設(shè)置為mono字體,而前面我已經(jīng)建立了mono字體列表,實際上就是更紗黑體,所以這里就相當(dāng)于告訴plot
,你有沒有特別指定字體啊,沒有的話就用更紗黑體吧。
- 測試結(jié)果,保存
.Rprofile
并啟動R,輸入
> plot(cos, -pi*2, pi*2, xlab='自變量', ylab='因變量',
main='一個余弦函數(shù)', font=3)
這里font=3
的意思是用斜體,我前面說了一直用這個mono的更紗黑體,道理就在這里,一般中文字體文件中不含斜體,其實有時候我們還是需要斜體的西文字體,更紗黑體剛好有斜體,所以就用它了。結(jié)果如圖
至此,R語言的默認中文繪圖環(huán)境已經(jīng)設(shè)置完畢,下面說一下第三方繪圖包中的亂碼問題
解決ggplot2
的中文亂碼
ggplot2
并沒有繼承基礎(chǔ)繪圖的配置,所以我們得給它單獨配置,不過也很簡單,打開~/.Rprofile
文件,再加一個hook函數(shù):
# 設(shè)置ggplot2使用中文字體
setHook(packageEvent("ggplot2", "attach"),
function(...) {
try({
theme_set(theme_get() +
theme(text=element_text(family='Sarasa Mono CL')))
})
}
)
是不是更簡單?其實在繪圖當(dāng)中,我們也可以臨時設(shè)置字體,只是每次都設(shè)置有點麻煩,我這樣一次性設(shè)置之后使用起來就非常方便了。
保存配置文件之后再打開R運行環(huán)境,輸入:
library(ggplot2)
qplot(1:10, rnorm(10), main='正太隨機抽取')
結(jié)果如下:
每個第三方包的工作方式都不一樣,這也就意味著每加入一個繪圖包,都可能要重新定義,例如lattice
就是另外一直方式。
解決lattice
的亂碼問題
lattice
沒有ggplot2
那么簡單明了,實際上我在中文網(wǎng)站上竟然沒有發(fā)現(xiàn)有人知道如何設(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)
})
}
)
好了,我們再來看看效果如何:
library(lattice)
histogram(~mpg, mtcars, main='每加侖英里數(shù)')