Python3下使用matplotlib画图添加中文注释乱码解决

Matplotlib是Python的一个很好的绘图包,但是其本身并不支持中文(貌似其默认配置中没有中文字体),所以如果绘图中出现了中文,就会出现乱码。

在《用Python作科学计算》一书中,有一个最小二乘拟合的例子,我用Python 3.3重写的代码如下:

# 最小二乘拟合示例
import numpy as np
from scipy.optimize import leastsq
import matplotlib.pyplot as plt
import matplotlib

def func(x, p):
    """
    数据拟合所用的函数: A*sin(2*pi*k*x + theta)
    """
    A, k, theta = p
    return A*np.sin(2*np.pi*k*x+theta)   

def residuals(p, y, x):
    """
    实验数据x, y和拟合函数之间的差,p为拟合需要找到的系数
    """
    return y - func(x, p)

x = np.linspace(0, -2*np.pi, 100)
A, k, theta = 10, 0.34, np.pi/6 # 真实数据的函数参数
y0 = func(x, [A, k, theta]) # 真实数据
y1 = y0 + 2 * np.random.randn(len(x)) # 加入噪声之后的实验数据    

p0 = [7, 0.2, 0] # 第一次猜测的函数拟合参数

# 调用leastsq进行数据拟合
# residuals为计算误差的函数
# p0为拟合参数的初始值
# args为需要拟合的实验数据
plsq = leastsq(residuals, p0, args=(y1, x))

print("真实参数:", [A, k, theta])
print("拟合参数", plsq[0]) # 实验数据拟合后的参数

plt.plot(x, y0, label="真实数据")
plt.plot(x, y1, label="带噪声的实验数据")
plt.plot(x, func(x, plsq[0]), label="拟合数据")
plt.legend()
plt.savefig('fit.jpg')
plt.show()
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

运行结果如下:

真实参数: [10, 0.34, 0.5235987755982988]
拟合参数 [ 10.02733131   0.3409059   -5.73652932]
 
 
  • 1
  • 2

这里图例使用的是中文,画出来的图如下:
raw

可以看出,图例中的中文并没有显示出来。

为了解决这个问题,可以使用如下方法:

因为乱码是Matplotlib缺少中文配置所导致的,所以我们只需要在程序中说明使用中文字体即可。

先选一个字体。在计算机中找到字体,选择一种中文字体,比如我这里用的是楷体
楷体

右键可以查看其属性从而得知字体名称:
shuxing

即该字体文件为simkai.ttf

然后在程序中定义Matplotlib的字体管理,这里将其命名为zhfont1,代码如下:

zhfont1 = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simkai.ttf')
 
 
  • 1

接着我们只要在绘图中出现中文的地方加上字体选项即可,在最小二乘拟合的例子中,我们只需要加上语句:

plt.legend(prop=zhfont1)
 
 
  • 1

完整的程序代码如下:

# 最小二乘拟合示例
import numpy as np
from scipy.optimize import leastsq
import matplotlib.pyplot as plt
import matplotlib

zhfont1 = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simkai.ttf')

def func(x, p):
    """
    数据拟合所用的函数: A*sin(2*pi*k*x + theta)
    """
    A, k, theta = p
    return A*np.sin(2*np.pi*k*x+theta)   

def residuals(p, y, x):
    """
    实验数据x, y和拟合函数之间的差,p为拟合需要找到的系数
    """
    return y - func(x, p)

x = np.linspace(0, -2*np.pi, 100)
A, k, theta = 10, 0.34, np.pi/6 # 真实数据的函数参数
y0 = func(x, [A, k, theta]) # 真实数据
y1 = y0 + 2 * np.random.randn(len(x)) # 加入噪声之后的实验数据    

p0 = [7, 0.2, 0] # 第一次猜测的函数拟合参数

# 调用leastsq进行数据拟合
# residuals为计算误差的函数
# p0为拟合参数的初始值
# args为需要拟合的实验数据
plsq = leastsq(residuals, p0, args=(y1, x))

print("真实参数:", [A, k, theta])
print("拟合参数", plsq[0]) # 实验数据拟合后的参数

plt.plot(x, y0, label="真实数据")
plt.plot(x, y1, label="带噪声的实验数据")
plt.plot(x, func(x, plsq[0]), label="拟合数据")
plt.legend(prop=zhfont1)
plt.savefig('fit.jpg')
plt.show()
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

运行后可以画出图像
fit

这样中文图例便正常显示了。

此外,在用LaTex写论文时,我们经常需要插入矢量格式的图,最好是eps或者pdf格式的图,即将存图的那行代码改为

plt.savefig('fit.pdf')
 
 
  • 1

但是使用以上代码保存生成的图为pdf格式时,可能会出现错误(如果没有出现,可以无视下面的内容了),错误提示缺少第三方字体。
error

这时我们只要把刚才的字体文件复制到Matplotlib的字体文件夹中即可,我是把Python安装到了E:\Program Files中,所以只要把simkai.ttf文件复制到如下文件夹中就ok了。

E:\Program Files\Python\Lib\site-packages\matplotlib\mpl-data\fonts\ttf
 
 
  • 1

如此一来,程序便能正确输出pdf格式的图片了。

最后,再附上一个简单的例子(注:该例子改用了宋体-simsun.ttc,但图像无法存成pdf格式,但若换成simhei.ttf或者simkai.ttf均可以存成pdf格式),代码如下:

#中文标题与坐标轴示例
import matplotlib.pyplot as plt
import matplotlib
zhfont1 = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
plt.xlabel('性别',fontproperties=zhfont1)
plt.ylabel('人数',fontproperties=zhfont1)
plt.title('直方图',fontproperties=zhfont1)
plt.xticks( (0,1),('男','女') ,fontproperties=zhfont1)
plt.bar(left=(0,1), height=(1,0.5), width=0.35)
plt.show()
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

画出的图像如下:
p2

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值