R畫圖中英文字型完美解決方案
fontforge.png
R語言用來做資料處理和分析很方便,藉助ggplot2能夠方便的畫出比較漂亮且資訊豐富的圖形,但是由於歷史原因,R對中文的支援並不是很好,尤其是作圖的時候需要一些特殊的技巧才能完美的展示中文字型,同時對於中英文混合的情況,經過一番摸索之後也找到了比較完美的方案。
一句話總結:在
plot
或者ggplot2
的theme
中設定family
引數,如需要儲存為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
能夠對標題、座標軸、座標刻度等分別設定不同的字型,具體使用方法請參考ggplot
的theme
函式。
如果需要將含有中文字型的圖形儲存為pdf
檔案,同樣可以利用前面講到的方案,最新版的showtext
包已經支援了ggplot2
,推薦使用此種方案。
中英文字型混合顯示
前面囉囉嗦嗦的說了一大推,其實總結起來無非是在plot
或者ggplot2
的theme
中設定family
引數,如需要儲存為pdf
檔案,則利用showtext
包新增字型即可。
但是有時候需要同時顯示中文和英文,而plot
和ggplot2
對同一個元素的字型只能設定一種字型,因此可能的解決方案就是使用中英文混合字型,比如知名度很高的YaHei
Consolas
混合字型,然而最近由於要寫畢業論文,需要黑體和Times New Roman的混合字型,網上搜了一圈沒搜到,只能動手製作一個了。Google後發現了一個開源專案:FontForge, 其安裝方法見官網說明,該專案能夠很方便的用來合併中英文字型,這個開源專案在處理字型上功能很強大,有GUI和命令列兩種使用方式,在Mac上其GUI依賴於X11
,但是X11
在最新版的Mac
OS上存在諸多問題,因此還是推薦使用命令列,使用起來也非常簡單,比如說我們想要合併黑體和Times New Roman,先把這兩個字型的字型檔案找出來,放在同一個資料夾下面,我這裡的檔名分別為simhei.ttf
和TimesNewRoman.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畫圖的字型問題基本完美解決。