我的Python心路历程 第十期 (10.8 股票实战之数据可视化中文显示问题)
plt图中显示中文是常见用法,但似乎调试起来没那么容易呢。见初始代码:
#展示效果设置
plt.figure('SNS图例', figsize=(18, 5))
编译错误UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 3: ordinal not in range(128)
首先,看看坐标中文显示方法。增加字体配置后的代码如下:
#字体配置
from pylab import *
from matplotlib.font_manager import FontProperties
#定义字体属性
font = FontProperties(fname=r"/System/Library/AssetsV2/com_apple_MobileAsset_Font6/4c66b413a81d594dc2fc430266c1629c30a5237b.asset/AssetData/STFANGSO.ttf", size=14) # “”里面为字体的相对地址 或者绝对地址
......
#测试中文
def testChinese():
plt.figure()
plt.xlabel(u"横坐标名称", fontproperties=font)
plt.ylabel(u"纵坐标名称", fontproperties=font)
plt.title(u"题目", fontproperties=font)
plt.plot([1,2,6,4], [4,5,6,9])
plt.show()
return
需要说明的是,如果设置font时只是写字体文件名的话,那么编译会报错IOError: [Errno 2] No such file or directory: 'STFANGSO.ttf'
。搜索对应字体文件并查询路径名后给予绝对路径后问题得以解决。
另外,有中文字符的代码必须使用u"算法"
,否则会编译报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)
错误代码如下:
plt.title(u"题目", fontproperties=font)
plt.plot([1,2,6,4], [4,5,6,9], marker='.', label="算法")
plt.show()
label处报错,优化后并加上标题和label中文代码如下:
#测试中文
def testChinese():
plt.figure(u"测试图例")
plt.xlabel(u"横坐标名称", fontproperties=font)
plt.ylabel(u"纵坐标名称", fontproperties=font)
plt.title(u"题目", fontproperties=font)
plt.plot([1,2,6,4], [4,5,6,9], marker='.', label=u"算法")
plt.show()
return
尽管编译通过了,但奇怪的是label并没有显示。
接下来,研究一下图中注释的中文显示方法。
细心朋友就会发现上图中label未显示,改为英文试试看效果。
plt.plot([1,2,6,4], [4,5,6,9], marker='.', label='label xxx')
运行结果表明label根本就没生效,何谈中文。是不是只有一个label的缘故呢?增加一个试试看。代码如下:
x = [1,2,3,4,5,6,7]
y1 = [4,5,6,9,5,6,7]
y2 = [5, 6, 7,4,5,6,9]
plt.plot(x, y1, color='r', linestyle='--', marker='>', label="shanghai")
plt.plot(x, y2, color='b', linestyle='--', marker='.', label='shenzhen')
plt.legend()
看来真的是只有一个无法显示label,显示的意义似乎也不大。
最后,直接更改label为中文。
plt.plot(x, y1, color='r', linestyle='--', marker='>', label=u"上海")
plt.plot(x, y2, color='b', linestyle='--', marker='.', label=u'深圳')
label显示是乱码,看来上面的字体设置方法不适用于图中中文显示。
为了实现中文也是醉了。查看了很多资料发现是字体库的事。
第一步,下载SimHei字体库。
第二步,将下载的字体库放在'/Downloads/python/gupiao/venv/lib/python2.7/site-packages/matplotlib/mpl-data/fonts/ttf'
文件夹中。
第三步,修改matplotlibrc
配置文件。(路径为“/Downloads/python/gupiao/venv/lib/python2.7/site-packages/matplotlib/mpl-data”下,建议先备份一个)
1、使用文本编辑器打开matplotlibrc 文件,找到font.family,并将font.family和font.sans-serif两行前的#删除;
2、在font.sans-serif后添加中文字体SimHei,其他的不变;
3、可以修改axes.unicode_minus,将True改为False,作用就是解决负号’-'显示为方块的问题。
4、修改完配置文件重启Python,在主任务代码中添加这几行代码:
#支持中文,让plot中的label也能用中文,即图表中的中文显示问题
mpl.rcParams['font.sans-serif'] = ['SimHei'] #['DejaVu Sans']
mpl.rcParams['axes.unicode_minus'] = False
第四步,编译依然报错,修改font_manager.py (所在路径为“/Users/xxxxx/Downloads/python/gupiao/venv/lib/python2.7/site-packages/matplotlib/font_manager.py”)
截图如下:(3.8供参考)
具体修改操作是:打开文件后直接找 self.defaultFamily,进行修改为我们的 SimHei 文件,注意那个 afm 要保留,它是另一种字体文件。
将文件中的DejaVu Sans修改成SimHei:
修改前:
self.defaultFamily = {
'ttf': 'DejaVu Sans',
'afm': 'Helvetica'}
self.defaultFont = {}
for fname in self.ttffiles:
_log.debug('trying fontname %s', fname)
if fname.lower().find('DejaVuSans.ttf')>=0:
self.defaultFont['ttf'] = fname
break
修改后:
self.ttffiles = findSystemFonts(paths) + findSystemFonts()
self.defaultFamily = {
'ttf': 'SimHei',#DejaVu Sans',
'afm': 'Helvetica'}
self.defaultFont = {}
for fname in self.ttffiles:
_log.debug('trying fontname %s', fname)
if fname.lower().find('SimHei.ttf')>=0:
self.defaultFont['ttf'] = fname
break
运行结果依然是乱码,编译错误为UserWarning: findfont: Font family [u'sans-serif'] not found. Falling back to DejaVu Sans (prop.get_family(), self.defaultFamily[fontext]))
第五步,如上编译错误可以断定设置未起作用,多半是缓存影响,故决定清缓存。
在python console中执行代码
import matplotlib
matplotlib.get_cachedir()
找到缓存路径。
在python terminal中执行rm -rf 路径
来清楚缓存。
哦耶,要的就是这个效果!