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

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

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

解決plot的亂碼問題

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

的方法建立一個(gè)空白的配置文件。

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

  1. 測(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é)果如圖

cosplot.png

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


rnormplot.png

每個(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ù)')
hist.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容