1. 程式人生 > >R畫圖中英文字型完美解決方案

R畫圖中英文字型完美解決方案


fontforge.png

R語言用來做資料處理和分析很方便,藉助ggplot2能夠方便的畫出比較漂亮且資訊豐富的圖形,但是由於歷史原因,R對中文的支援並不是很好,尤其是作圖的時候需要一些特殊的技巧才能完美的展示中文字型,同時對於中英文混合的情況,經過一番摸索之後也找到了比較完美的方案。

一句話總結:在plot或者ggplot2theme中設定family引數,如需要儲存為pdf檔案,則利用showtext包新增字型,如需分別指定中英文字型,就製作合適的中英文混合字型。

原生作圖函式的中文顯示

plot函式中設定family引數

在R中,使用plot函式畫圖時如果不指定字型,中文會顯示為亂碼,比如下面的語句:

 plot(c(1:10), xlab = '橫軸', ylab = '縱軸', 
      main = '中文標題 Title')

得到的圖形為:


06c2ffee487f8d7266b15caa830dba5f.png

此時可以通過設定family屬性來顯示中文字型,如下所示:

plot(c(1:10), xlab = '橫軸', ylab = '縱軸', 
     main = '中文標題 Title', family = 'SimSun')

得到的圖形為:


b68c02508473bdd014f61fd7df667434.png

可以發現中文根據設定顯示為了宋體,family

的值可以設定為任何在電腦中已經安裝的字型名稱,只要該字型包含中文字元,那麼就可以正常顯示中文,此外,如果想要分別設定主標題、副標題、座標軸等的字型樣式,在plot函式中設定font.main,font.sub,font.axis,font.lab 即可。

通過設定family引數能夠正常顯示中文,但是如果想要將畫好的圖形儲存下來還需要費一番周折,對於包含中文的圖形,如果儲存為png, jpg, tiff等格式,由於這些都是柵格圖形,均是有一定數目的畫素點組成,因此不存在字型能否載入的問題,可以直接進行儲存。

但是大部分情況下我們希望能夠將圖形儲存為向量格式,因為向量格式的檔案能夠無限放大不失真,並且佔用磁碟空間小,方便儲存與後續處理,如果有需要的話可以匯出為任意解析度的柵格影象。然而通過設定family

引數得到的包含中文字元的圖形在儲存為pdf格式的時候會出錯,比如執行下面的語句:

pdf('test.pdf')
plot(c(1:10), xlab = '橫軸', ylab = '縱軸', 
     main = '中文標題 Title', family = 'SimSun')
dev.off()

會得到如下輸出:

Error in axis(side = side, at = at, labels = labels, ...) : 字型類別出錯
此外: Warning messages:
1: In axis(side = side, at = at, labels = labels, ...) :
  PostScript字型資料庫裡找不到'SimSun'這個字體系列
  .........

錯誤原因提示的也很清楚,生成pdf檔案的圖形裝置的字型資料庫中找不到指定的字型,解決方案是通過pdf('test.pdf', family = 'GB1')設定pdf圖形裝置使用GB1字型,這會呼叫系統預設的中文字型,如果想要使用指定的中文字型,這種方法就不起作用了,這種情況下一種可能的方法是利用extrafont包註冊特定的字型,然後呼叫Cario包的CarioPDF來生成pdf檔案,但是這種方案比較繁瑣,並且很容易失敗。

比較好的解決方案是利用showtext包,使用起來非常簡單,在此感謝此包的作者,使用方法如下:

library(showtext)
showtext.auto(enable = TRUE)
font.add('SimSun', 'simsun.ttc')
pdf('test.pdf')
plot(c(1:10), xlab = '橫軸', ylab = '縱軸', 
     main = '中文標題 Title', family = 'SimSun')
dev.off()

得到的pdf檔案如下:
![Uploading 62a1a74efedab3a3855c3a78d1b7a882_854328.png . . .]


c76dfdecd4bc238f054e3c2f2892e1bc.png

showtext包理論上能夠呼叫系統已安裝的任何字型,完整的字型列表可以通過font.files()檢視。

有強迫症的同學可能會注意到,標題中的中英文看起來很不協調,這是因為很多中文字型的英文部分不夠美觀,至於如何在同一行文字中同時使用中文字型和英文字型,會在最後介紹一種可行方法。

ggplot2顯示中文字型

ggplot2的畫圖功能非常強大,初期不太容易上手,但是習慣了之後會發現真的好用,在此不做過多介紹,只關注顯示中文的方法,和plot函式類似,如果只是希望顯示中文或者儲存為柵格影象,只需要在畫圖的時候設定family引數即可,一種可用的方法如下:

library(ggplot2)
ggplot(data.frame(x = rnorm(100))) +
    geom_histogram(aes(x), fill = 'purple', alpha = 0.6) +
    labs(x = 'X 取值', y = '頻數 Count') +
    theme(text = element_text(family = 'SimSun'))

結果為:


62a1a74efedab3a3855c3a78d1b7a882.png

如果不通過theme(text = element_text(family = 'SimSun'))設定字型引數,則會出現中文亂碼,同樣,ggplot2能夠對標題、座標軸、座標刻度等分別設定不同的字型,具體使用方法請參考ggplottheme函式。

如果需要將含有中文字型的圖形儲存為pdf檔案,同樣可以利用前面講到的方案,最新版的showtext包已經支援了ggplot2,推薦使用此種方案。

中英文字型混合顯示

前面囉囉嗦嗦的說了一大推,其實總結起來無非是在plot或者ggplot2theme中設定family引數,如需要儲存為pdf檔案,則利用showtext包新增字型即可。

但是有時候需要同時顯示中文和英文,而plotggplot2對同一個元素的字型只能設定一種字型,因此可能的解決方案就是使用中英文混合字型,比如知名度很高的YaHei Consolas混合字型,然而最近由於要寫畢業論文,需要黑體和Times New Roman的混合字型,網上搜了一圈沒搜到,只能動手製作一個了。Google後發現了一個開源專案:FontForge, 其安裝方法見官網說明,該專案能夠很方便的用來合併中英文字型,這個開源專案在處理字型上功能很強大,有GUI和命令列兩種使用方式,在Mac上其GUI依賴於X11,但是X11在最新版的Mac OS上存在諸多問題,因此還是推薦使用命令列,使用起來也非常簡單,比如說我們想要合併黑體和Times New Roman,先把這兩個字型的字型檔案找出來,放在同一個資料夾下面,我這裡的檔名分別為simhei.ttfTimesNewRoman.ttf,然後在同一個資料夾下面新建一個指令碼檔案mergefont.pe,內容如下:

Open("simhei.ttf")
SelectAll()
ScaleToEm(1024)
Generate("temp.ttf", "", 0x14)
Close()

# Open English font and merge to the Chinese font
Open("TimesNewRoman.ttf")
SelectAll()
ScaleToEm(1024)

MergeFonts("temp.ttf")
SetFontNames("Broman", "Broman", "SimHei Times New Roman Hybrid", "Regular", "")
Generate("Broman.ttf", "", 0x14)
Close()

如果已經成功的安裝了fontforge,在命令列切換到當前目錄並執行fontforge -script mergefont.pe,即可生成Broman.ttf字型檔案,然後雙擊安裝即可。

測試一下生成的Broman混合字型,程式碼如下:

library(ggplot2)
library(showtext)
showtext.auto(enable = TRUE)
font.add('Broman', 'Broman.ttf')
pdf('test.pdf')
ggplot(data.frame(x = rnorm(100))) +
    geom_histogram(aes(x), fill = 'purple', alpha = 0.6) +
    labs(x = 'X 取值', y = '頻數 Count', title = '標題 Title') +
    theme(text = element_text(family = 'Broman'))
dev.off()

得到的pdf檔案如下:


aa84fbb65641901bb50423c11e873c5e.png

可以看到中文字型顯示為黑體,英文字型顯示為Times New Roman, 至此,R畫圖的字型問題基本完美解決。