解決R語言繪圖中的中文亂碼問題

在R語言環(huán)境中,畫圖有兩種情況,一是直接用R自帶的繪圖功能,也就是默認的plot函數(shù)。還一種是用第三方繪圖包,例如ggplot2lattice這樣的繪圖包,要在這兩種情況下都能正常顯示中文,操作方式是不一樣的。

我的操作系統(tǒng)是macOS 10.13.6,R語言安裝的是3.6.1版本,從網(wǎng)上下載了免費的思源黑體和更紗黑體(Sarasa Mono)字體文件,下面以此為基礎(chǔ)說一下操作步驟::

解決plot的亂碼問題

  1. 確定在$HOME目錄中有.Rprofile文件,如果你的系統(tǒng)中沒有,可以用
touch ~/.Rprofile

的方法建立一個空白的配置文件。

  1. 用編輯器打開.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,你有沒有特別指定字體啊,沒有的話就用更紗黑體吧。

  1. 測試結(jié)果,保存.Rprofile并啟動R,輸入
> plot(cos, -pi*2, pi*2, xlab='自變量', ylab='因變量', 
    main='一個余弦函數(shù)', font=3)

這里font=3的意思是用斜體,我前面說了一直用這個mono的更紗黑體,道理就在這里,一般中文字體文件中不含斜體,其實有時候我們還是需要斜體的西文字體,更紗黑體剛好有斜體,所以就用它了。結(jié)果如圖

cosplot.png

至此,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é)果如下:


rnormplot.png

每個第三方包的工作方式都不一樣,這也就意味著每加入一個繪圖包,都可能要重新定義,例如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ù)')
hist.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容