中文字型問題處理
Matplotlib 顯示中文時常見的問題是:
- 圖表中的中文字變成方框
- 出現 `Glyph xxxx missing from current font`
- 中文正常,但負號 `−` 顯示異常
通常是因為 Matplotlib 預設字型不支援中文。解法是安裝中文字型,並在 Matplotlib 中指定它。
## 1. 安裝中文字型
可選用以下常見字型:
### Windows
通常可使用:
- `Microsoft JhengHei`:微軟正黑體
- `Microsoft YaHei`:微軟雅黑
- `SimSun`:宋體
### macOS
通常可使用:
- `PingFang TC`
- `Heiti TC`
- `Arial Unicode MS`
### Linux
可安裝 Noto CJK 字型:
```bash
sudo apt update
sudo apt install fonts-noto-cjk
```
常見字型名稱:
- `Noto Sans CJK TC`
- `Noto Serif CJK TC`
也可以自行下載並安裝,例如 Noto Sans CJK、思源黑體等。
---
## 2. 在程式中指定中文字型
### 方法一:設定全域字型
```python
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = [
"Microsoft JhengHei", # Windows
"PingFang TC", # macOS
"Noto Sans CJK TC", # Linux
"DejaVu Sans" # 備援字型
]
# 解決負號顯示成方框的問題
plt.rcParams["axes.unicode_minus"] = False
plt.plot([-2, -1, 0, 1, 2], [1, 4, 2, 5, 3])
plt.title("中文圖表標題")
plt.xlabel("時間")
plt.ylabel("數值")
plt.show()
```
不過,列表中的字型必須確實安裝在目前的作業系統中。
---
## 3. 指定單一字型檔案
如果 Matplotlib 找不到字型名稱,可以直接指定 `.ttf` 或 `.ttc` 字型檔:
```python
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(
fname="/path/to/your/font.ttf"
)
plt.plot([1, 2, 3], [2, 4, 3])
plt.title("中文標題", fontproperties=font)
plt.xlabel("橫軸", fontproperties=font)
plt.ylabel("縱軸", fontproperties=font)
plt.show()
```
例如:
```python
font = FontProperties(
fname="C:/Windows/Fonts/msjh.ttc"
)
```
Linux 可能是:
```python
font = FontProperties(
fname="/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
)
```
---
## 4. 查詢 Matplotlib 找到的字型
可以使用以下程式查看指定字型是否存在:
```python
from matplotlib.font_manager import findfont
import matplotlib
print(findfont("Microsoft JhengHei"))
print(matplotlib.get_cachedir())
```
如果找不到指定字型,通常會回傳 Matplotlib 預設字型的位置,表示該字型可能尚未安裝或名稱不正確。
也可以列出目前可用的字型:
```python
from matplotlib.font_manager import fontManager
fonts = sorted({
font.name for font in fontManager.ttflist
})
for font in fonts:
if any(keyword in font.lower()
for keyword in ["noto", "hei", "jheng", "pingfang", "cjk"]):
print(font)
```
---
## 5. 清除 Matplotlib 字型快取
安裝新字型後,Matplotlib 可能仍使用舊的字型快取。可以先關閉所有 Python 程式,再刪除快取目錄。
查詢快取位置:
```python
import matplotlib
print(matplotlib.get_cachedir())
```
常見情況:
- Linux/macOS:`~/.cache/matplotlib`
- Windows:使用者目錄下的 `.matplotlib`
刪除其中的字型快取檔,例如:
```text
fontlist-v*.json
```
重新執行 Python 程式後,Matplotlib 會重新建立字型快取。
---
## 6. 使用 `rc_context` 只套用到特定圖表
如果不想影響整個程式,可以只對某一段繪圖設定:
```python
import matplotlib.pyplot as plt
with plt.rc_context({
"font.sans-serif": ["Microsoft JhengHei"],
"axes.unicode_minus": False
}):
plt.plot([1, 2, 3], [3, 1, 4])
plt.title("中文圖表")
plt.show()
```
---
## 7. 儲存圖片時也要確認字型
設定完成後,輸出圖片通常會正常顯示中文:
```python
plt.savefig("chart.png", dpi=300, bbox_inches="tight")
```
如果輸出 PDF 或 SVG,建議設定字型嵌入方式:
```python
import matplotlib as mpl
mpl.rcParams["pdf.fonttype"] = 42
mpl.rcParams["ps.fonttype"] = 42
```
---
## 常用的完整範例
```python
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
plt.rcParams["font.sans-serif"] = [
"Microsoft JhengHei",
"PingFang TC",
"Noto Sans CJK TC"
]
plt.rcParams["axes.unicode_minus"] = False
x = ["一月", "二月", "三月", "四月"]
y = [12, 18, 15, 21]
plt.figure(figsize=(8, 4))
plt.bar(x, y)
plt.title("每月銷售量")
plt.xlabel("月份")
plt.ylabel("銷售數量")
plt.tight_layout()
plt.show()
```
若仍然無法顯示中文,依序檢查:
1. 作業系統是否真的安裝中文字型
2. 字型名稱是否正確
3. Matplotlib 是否找到該字型
4. 是否需要清除 Matplotlib 字型快取
5. `fontproperties` 是否套用到標題、座標軸、圖例等文字元素
相關學習地圖、教學課程
Python 資料工程