如何在matplotlib中使用Unicode符号?

12
import matplotlib.pyplot as pyplot

pyplot.figure()
pyplot.xlabel(u"\u2736")
pyplot.show()

这是我能创建的最简单的代码,用来展示我的问题。轴标签符号应该是一个六角星形,但显示为方块。我该如何更改它,以便显示星形?我已经尝试添加注释:

#-*- coding: utf-8 -*-

像之前的答案建议的那样,但它没有起作用,还尝试使用 matplotlib.rcmatplotlib.rcParams 也没有起作用。求助。


1
\u2736代表星号吗? - styvane
3个回答

8
你需要使用一种包含所需Unicode字符的字体,STIX字体应该包含星号符号。 你需要找到或下载STIX字体,当然,任何其他带有给定符号的ttf文件也可以。
import matplotlib.pyplot as pyplot
from matplotlib.font_manager import FontProperties

if __name__ == "__main__":
    pyplot.figure() 
    prop = FontProperties()
    prop.set_file('STIXGeneral.ttf')
    pyplot.xlabel(u"\u2736", fontproperties=prop)
    pyplot.show()

5
为了补充@arjenve的回答。要绘制Unicode字符,首先找到包含该字符的字体,然后使用该字体在Matplotlib中绘制字符。

找到包含该字符的字体

根据这篇文章,我们可以使用fontTools包来查找包含我们想要绘制的字符的字体。
from fontTools.ttLib import TTFont
import matplotlib.font_manager as mfm

def char_in_font(unicode_char, font):
    for cmap in font['cmap'].tables:
        if cmap.isUnicode():
            if ord(unicode_char) in cmap.cmap:
                return True
    return False

uni_char =  u"✹"
# or uni_char = u"\u2739"

font_info = [(f.fname, f.name) for f in mfm.fontManager.ttflist]

for i, font in enumerate(font_info):
    if char_in_font(uni_char, TTFont(font[0])):
        print(font[0], font[1])

这个脚本将打印字体路径和字体名称的列表(所有这些字体都支持该Unicode字符)。下面是示例输出。

enter image description here

然后,我们可以使用以下脚本来绘制该字符(见下图)。
import matplotlib.pyplot as plt
import matplotlib.font_manager as mfm

font_path = '/usr/share/fonts/gnu-free/FreeSerif.ttf'
prop = mfm.FontProperties(fname=font_path)
plt.text(0.5, 0.5, s=uni_char, fontproperties=prop, fontsize=20)

plt.show()

enter image description here


1
我试图实现@jdhao的代码,但由于我的库中还有类型0字体,所以它经常会出错。因此,这是他的代码的一个调整版本,它不会在使用类型0字体时出错,并且通过提供函数的uni字符列表而不仅仅是一个uni字符,使得可以在同一字体中找到多个uni字符。

有关更多详细信息,请阅读代码中的注释。

#!/usr/bin/env python
from fontTools.ttLib import TTFont
import matplotlib.font_manager as mfm

def print_if_char_in_font(list_unichars, print_true_only=False):

  def char_in_font(unicode_char, font):
    if font.endswith('.ttc'): fontNo = 0 #default is for type -1 so type 0 fonts are going to break the code without this line
    else: fontNo = -1
    font=TTFont(font, fontNumber=fontNo)
    for cmap in font['cmap'].tables: 
      if cmap.isUnicode():
        for i in unicode_char: #tries to match all uni chars with font cmap
          if ord(i) not in cmap.cmap:
            return False
    return True #returns true if all uni chars in given list were found successfully

  font_info = [(f.fname, f.name) for f in mfm.fontManager.ttflist] #list of all font dirs & font names in system

  for i, font in enumerate(font_info):
    try:
      if char_in_font(list_unichars, font[0]) == True: #calls for the defined searching func and checks if True
        print('Yess!! loc:{0}; font name:{1}'.format(font[0], font[1])) #print statement if find is successful
      elif print_true_only==False: print('No :( -- {0}'.format(font[1])) #print statement is find fails
    except:
      print('Error!! Unable to load: {0}, font name: {1}'.format(font[0], font[1])) #if unable to load(type 1 fonts?)
  return

def main(): #this is newbie friendly code, only need to touch 'main' for it to work with your data!
  uni_char = [u'1',u'2', u'*', u"✹"]
  # uni_char = [u"✹"] #or [u"\u2739"] #put inside list even if finding just one char!
  print_if_char_in_font(uni_char, print_true_only=True) #print_true_only is just going to output fonts that satisfy the search

###e.g
# Yess!! loc:C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\mpl-data\fonts\ttf\DejaVuSansMono-Bold.ttf; font name:DejaVu Sans Mono
# Yess!! loc:C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\mpl-data\fonts\ttf\DejaVuSans.ttf; font name:DejaVu Sans

### print_true_only=False is going to output for all fonts including those which do not satisfy:
# No :( -- Times New Roman
# Yess!! loc:C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\matplotlib\mpl-data\fonts\ttf\DejaVuSans-Bold.ttf; font name:DejaVu Sans
# No :( -- Sitka Small

if __name__ == '__main__':
  main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接