How to mix Chinese and English with MatPlotLib

Viewed 2274

Background

MatPlotLib is a fantastic graphic package. But when I sometimes need to plot dataset in Chinese. I have found some problem.

There are two methods for representing non-English font with MatPlotLib.

Method 1

import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # YaHei is one common Chinese font
mpl.rcParams['axes.unicode_minus'] = False # Repair the bug of representing '-'as "square"

Wiht this method, all the text and number showing in the figure are all in the Chinese Font.

Method 2

Differently, I predefine the pathway of the some chinese font and call it when I need to use.

from matplotlib.font_manager import FontProperties 
chinese = FontProperties(fname=r'/Library/Fonts/Microsoft/SimHei.ttf', size=20) 
ax = plt.gca() 
ax.set_title(u'能量随时间的变化', fontproperties=chinese) 

My Problem

When a string contains Chinese text and English text together (e.g, Chinese as the variable, and it should come with some units: kg, m/s.)

质量 == Mass
as.set_xlabel(u'质量' + '(kg)') ==> Want to define their font sepearetly.

So, I want the string can be mixed up with Chinese and English font together as an unit?

Is it possible to achieve that?

2 Answers
  1. I think Latex is the potential solution.In LaTex package, xeCJK is a package which provides Chinese,Japanese and Korean support. You can read matplotlib document about Tex. Matplotlib could use Tex render text and equation. In fact , it's also the dilemma for me. And the method above is just my guess. Of Course I haven't prove it.
  2. Anther way to solve the problem is using some font support Chinese and English. For instance, SimHei is a appropriate font. I know it's compromise in Paper Publication in China.
  3. Finally it's an example from the blog which using text() to specify Chinese and English in xlabel.

OK, I have make some trials on method 1. The result supports what I guessed. Here is my codes.

import matplotlib
mpl.use('pgf') # stwich backend to pgf
import matplotlib.pyplot as plt
    plt.rcParams.update({
    "text.usetex": True,# use default xelatex
    "pgf.rcfonts": False,# turn off default matplotlib fonts properties
    "pgf.preamble": [
         r'\usepackage{fontspec}',
         r'\setmainfont{Times New Roman}',# EN fonts Romans
         r'\usepackage{xeCJK}',# import xeCJK
         r'\setCJKmainfont{SimSun}',# set CJK fonts as SimSun
         r'\xeCJKsetup{CJKecglue=}',# turn off one space between CJK and EN fonts
         ]
})
plt.rcParams['savefig.dpi']=300
plt.figure(figsize=(4.5, 2.5))
plt.plot(range(5))
plt.text(2.5, 2., "\CJKfontspec{SimHei}{黑体标注}")# Annotation by SimHei
plt.xlabel("宋体坐标标签(units)")# CJK&EN fonts mixed
plt.tight_layout(.5)
plt.savefig('examples.png')

examples

Usually, we want "Times New Roman" for the English font and "SimSun" for the Chinese font. The "font.family" defines the global font. For the units, we can use the math formula. However, there is not "Times New Roman" font for the formula. So I use "stix" to replace the "Times New Roman".

import matplotlib.pyplot as plt
rc = {"font.family" : "Times New Roman",
      "mathtext.fontset" : "stix",
      }
plt.rcParams.update(rc)enter image description here
fig,ax = plt.subplots(dpi = 300)
ax.set_xlabel(r'密度$\mathrm{kg/m}^3$',fontname = 'SimSun',fontsize = 20)
ax.text(0.2,0.8,r'宋体 $\mathrm{Times New Roman}$(正体)',fontname = 'SimSun',fontsize = 20)
ax.text(0.2,0.6,r'宋体 $Times New Roman$(斜体)',fontname = 'SimSun',fontsize = 20)
ax.text(0.2,0.4,r'$\mathrm{m^3}\ m^3$',fontsize = 30)
fig.tight_layout()
plt.show()

Hope it can help you!

Related