Matplotlib自定义标记/符号

41

有一个指南: http://matplotlib.org/examples/pylab_examples/scatter_symbol.html enter image description here

# http://matplotlib.org/examples/pylab_examples/scatter_symbol.html
from matplotlib import pyplot as plt
import numpy as np
import matplotlib

x = np.arange(0.0, 50.0, 2.0)
y = x ** 1.3 + np.random.rand(*x.shape) * 30.0
s = np.random.rand(*x.shape) * 800 + 500

plt.scatter(x, y, s, c="g", alpha=0.5, marker=r'$\clubsuit$',
            label="Luck")
plt.xlabel("Leprechauns")
plt.ylabel("Gold")
plt.legend(loc=2)
plt.show()

但是如果你像我一样不想使用俱乐部标记,那怎么办呢?

你该如何制作自己的标记_________?

更新

我喜欢这种特殊标记类型的原因是它可以使用简单的matplotlib语法进行调整:

from matplotlib import pyplot as plt
import numpy as np
import matplotlib

x = np.arange(0.0, 50.0, 2.0)
y = x ** 1.3 + np.random.rand(*x.shape) * 30.0
s = np.random.rand(*x.shape) * 800 + 500

plt.plot(x, y, "ro", alpha=0.5, marker=r'$\clubsuit$', markersize=22)
plt.xlabel("Leprechauns")
plt.ylabel("Gold")
plt.show()

在此输入图片描述


2
你看过这个了吗? - moooeeeep
是的,我确实尝试过。但对我来说并没有奏效。我喜欢matplotlib示例代码中的'c="g"',我将其解释为绘图的颜色调整(写作时没有Python shell进行测试)。 - Norfeldt
2个回答

57

我发现它只是使用了mathtext符号,而没有引用matplotlib模块中存储的任何特殊的基于向量的标记...

from matplotlib import pyplot as plt
import numpy as np
from numpy.random import randint
import matplotlib

x = np.arange(0.0, 100.0, 2.0)
y = x ** 1.3 + np.random.rand(*x.shape) * 30.0
s = np.random.rand(*x.shape) * 800 + 500

markers = ['\\alpha', '\\beta', '\gamma', '\sigma','\infty', \
            '\spadesuit', '\heartsuit', '\diamondsuit', '\clubsuit', \
            '\\bigodot', '\\bigotimes', '\\bigoplus', '\imath', '\\bowtie', \
            '\\bigtriangleup', '\\bigtriangledown', '\oslash' \
           '\ast', '\\times', '\circ', '\\bullet', '\star', '+', \
            '\Theta', '\Xi', '\Phi', \
            '\$', '\#', '\%', '\S']

def getRandomMarker():
    return "$"+markers[randint(0,len(markers),1)]+"$"

def getMarker(i):
    # Use modulus in order not to have the index exceeding the lenght of the list (markers)
    return "$"+markers[i % len(markers)]+"$"

for i, mi in enumerate(markers):
    plt.plot(x[i], y[i], "b", alpha=0.5, marker=getRandomMarker(), markersize=randint(16,26,1))
    plt.plot(x[i], y[i]+50, "m", alpha=0.5, marker=getMarker(i), markersize=randint(16,26,1))
    # Let's see if their "center" is located where we expect them to be...
    plt.plot(x[i], y[i]+100, "y", alpha=0.5, marker=getMarker(i), markersize=24)
    plt.plot(x[i], y[i]+100, "k+", markersize=12, markeredgewidth=2)

plt.xlabel("x-axis")
plt.ylabel("y-axis")
plt.xlim( -5, plt.xlim()[1]+5 )
plt.ylim( 0, plt.ylim()[1]*1.1 )
plt.gcf().set_size_inches(12,6)
plt.show()

勾选图片


12
我试图寻找一个“填充的心”因为 \heartsuit 只是一个轮廓。使用Unicode标记对我有用:marker=ur'$\u2665$' - patricksurry
4
对于那些想要去除普通字母/单词斜体的人,使用\mathrm\rm数学文本命令可以实现。例如,对于字母M,可以使用marker=r'$\mathrm{M}$' - Andy
所有支持的符号列表:https://matplotlib.org/stable/tutorials/text/mathtext.html#symbols - CGFoX
你应该使用r-strings来避免需要双反斜杠转义LaTeX命令,例如markers = [r'\alpha', r'\beta', r'\gamma', ...] - parmentelat

25

matplotlib最灵活的选项是标记路径

我使用Inkscape将微笑脸SVG转换为单个SVG路径。 Inkscape还可以对位图图像进行路径跟踪。 然后我使用SVG路径,使用svgpath2mpl将其转换为matplotlib.path.Path

!pip install svgpath2mpl matplotlib
from svgpath2mpl import parse_path

import matplotlib.pyplot as plt      
import numpy as np                   
# Use Inkscape to edit SVG, 
# Path -> Combine to convert multiple paths into a single path
# Use Path -> Object to path to convert objects to SVG path
smiley = parse_path("""m 739.01202,391.98936 c 13,26 13,57 9,85 -6,27 -18,52 -35,68 -21,20 -50,23 -77,18 -15,-4 -28,-12 -39,-23 -18,-17 -30,-40 -36,-67 -4,-20 -4,-41 0,-60 l 6,-21 z m -302,-1 c 2,3 6,20 7,29 5,28 1,57 -11,83 -15,30 -41,52 -72,60 -29,7 -57,0 -82,-15 -26,-17 -45,-49 -50,-82 -2,-12 -2,-33 0,-45 1,-10 5,-26 8,-30 z M 487.15488,66.132209 c 121,21 194,115.000001 212,233.000001 l 0,8 25,1 1,18 -481,0 c -6,-13 -10,-27 -13,-41 -13,-94 38,-146 114,-193.000001 45,-23 93,-29 142,-26 z m -47,18 c -52,6 -98,28.000001 -138,62.000001 -28,25 -46,56 -51,87 -4,20 -1,57 5,70 l 423,1 c 2,-56 -39,-118 -74,-157 -31,-34 -72,-54.000001 -116,-63.000001 -11,-2 -38,-2 -49,0 z m 138,324.000001 c -5,6 -6,40 -2,58 3,16 4,16 10,10 14,-14 38,-14 52,0 15,18 12,41 -6,55 -3,3 -5,5 -5,6 1,4 22,8 34,7 42,-4 57.6,-40 66.2,-77 3,-17 1,-53 -4,-59 l -145.2,0 z m -331,-1 c -4,5 -5,34 -4,50 2,14 6,24 8,24 1,0 3,-2 6,-5 17,-17 47,-13 58,9 7,16 4,31 -8,43 -4,4 -7,8 -7,9 0,0 4,2 8,3 51,17 105,-20 115,-80 3,-15 0,-43 -3,-53 z m 61,-266 c 0,0 46,-40 105,-53.000001 66,-15 114,7 114,7 0,0 -14,76.000001 -93,95.000001 -76,18 -126,-49 -126,-49 z""")
smiley.vertices -= smiley.vertices.mean(axis=0)
x = np.linspace(-3, 3, 20)          
plt.plot(x, np.sin(x), marker=smiley, markersize=20, color='c')
plt.show()

Google Colab链接

由上述代码片段创建的图表


不错!有什么方法可以用自定义颜色填充标记吗? - CGFoX
此外,smiley.vertices -= smiley.vertices.mean(axis=0) 是做什么用的?由于某种原因,我的图标显示是倒置的。有任何想法为什么? - CGFoX
参考资料,我找到了这个教程,它更详细地介绍了如何实现这一点:https://petercbsmith.github.io/marker-tutorial.html - BoZenKhaa

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