Matplotlib——带有半满标记的散点图

Matplotlib--scatter plot with half filled markers

问题:在matplotlib中使用散点图,有没有简单的方法得到一个半满的标记?

我知道使用线图可以轻松完成半填充标记,但我想使用 'scatter' 因为我想使用标记大小和颜色(即替代标记面颜色)来表示其他数据。 (我相信使用散点图会更容易,因为我想从大型数据集中自动制作大量图表。)

我似乎无法使用散点图正确制作半填充标记。也就是说,绘图显示的不是半满标记,而是半个标记。我一直在使用 matplotlib.markers.MarkerStyle,但这似乎只让我走到了一半。我可以使用下面的代码获得以下输出。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.markers import MarkerStyle

plt.scatter(1, 1, marker=MarkerStyle('o', fillstyle='full'), edgecolors='k', s=500)
plt.scatter(2, 2, marker=MarkerStyle('o', fillstyle='left'), edgecolors='k', s=500)
plt.scatter(3, 3, marker=MarkerStyle('o', fillstyle='right'), edgecolors='k', s=500)
plt.scatter(4, 4, marker=MarkerStyle('o', fillstyle='top'), edgecolors='k', s=500)
plt.scatter(5, 5, marker=MarkerStyle('o', fillstyle='bottom'), edgecolors='k', s=500)

plt.show()

如评论中所述,我不明白您为什么必须使用 plt.scatter,但如果您愿意,可以伪造一个组合标记:

from matplotlib.markers import MarkerStyle
from matplotlib import pyplot as plt

#data generation
import pandas as pd
import numpy as np
np.random.seed(123)
n = 10
df = pd.DataFrame({"X": np.random.randint(1, 20, n), 
      "Y": np.random.randint(10, 30, n), 
      "S": np.random.randint(50, 500, n), 
      "C1": np.random.choice(["red", "blue", "green"], n),
      "C2": np.random.choice(["yellow", "grey"], n)})

fig, ax = plt.subplots()

ax.scatter(df.X, df.Y, s=df.S, c=df.C1, edgecolor="black", marker=MarkerStyle("o", fillstyle="right"))
ax.scatter(df.X, df.Y, s=df.S, c=df.C2, edgecolor="black", marker=MarkerStyle("o", fillstyle="left"))
    
plt.show()

示例输出:

当然,这也适用于连续数据:

from matplotlib import pyplot as plt
from matplotlib.markers import MarkerStyle

import pandas as pd
import numpy as np
np.random.seed(123)
n = 10
df = pd.DataFrame({"X": np.random.randint(1, 20, n), 
      "Y": np.random.randint(10, 30, n), 
      "S": np.random.randint(100, 1000, n), 
      "C1": np.random.randint(1, 100, n),
      "C2": np.random.random(n)})

fig, ax = plt.subplots(figsize=(10,8))

im1 = ax.scatter(df.X, df.Y, s=df.S, c=df.C1, edgecolor="black", marker=MarkerStyle("o", fillstyle="right"), cmap="autumn")
im2 = ax.scatter(df.X, df.Y, s=df.S, c=df.C2, edgecolor="black", marker=MarkerStyle("o", fillstyle="left"), cmap="winter")
cbar1 = plt.colorbar(im1, ax=ax)
cbar1.set_label("right half", rotation=90)
cbar2 = plt.colorbar(im2, ax=ax)
cbar2.set_label("left half", rotation=90)

plt.show()

示例输出:

But be reminded that plt.plot with marker definitions might be faster for large-scale datasets: The plot function will be faster for scatterplots where markers don't vary in size or color.