Seaborn 散点图设置空心标记而不是填充标记
Seaborn scatterplot set hollow markers instead of filled markers
如何使用 Seaborn 散点图将标记设置为空心圆而不是实心圆?
这是一个简单的例子:
import pandas as pd
import seaborn as sns
df = pd.DataFrame(
{'x': [3,2,5,1,1,0],
'y': [1,1,2,3,0,2],
'cat': ['a','a','a','b','b','b']}
)
sns.scatterplot(data=df, x='x', y='y', hue='cat')
我尝试了以下方法但没有成功;其中大部分不会抛出错误,而是产生与上面相同的图。我认为这些不起作用,因为颜色是使用 hue
参数设置的,但我不确定修复方法是什么。
sns.scatterplot(data=df, x='x', y='y', hue='cat', facecolors = 'none')
sns.scatterplot(data=df, x='x', y='y', hue='cat', facecolors = None)
sns.scatterplot(data=df, x='x', y='y', hue='cat', markerfacecolor = 'none')
sns.scatterplot(data=df, x='x', y='y', hue='cat', markerfacecolor = None)
with sns.plotting_context(rc={"markerfacecolor": None}):
sns.scatterplot(data=df, x='x', y='y', hue='cat')
我使用 seaborn.FacetGrid
修改了您的代码,如下所示(基于 @cphlewis 此处提供的 ):
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
x1 = [3,2,5]
y1 = [1,1,2]
x2 = [1,1,0]
y2 = [3,0,2]
df1 = pd.DataFrame({'x1':x1, 'y1':y1})
df2 = pd.DataFrame({'x2':x2, 'y2':y2})
df = pd.concat([df1.rename(columns={'x1':'x','y1':'y'})
.join(pd.Series(['a']*len(df1), name='df')),
df2.rename(columns={'x2':'x','y2':'y'})
.join(pd.Series(['b']*len(df2), name='df'))],
ignore_index=True)
pal = dict(a="blue", b="red")
g = sns.FacetGrid(df, hue='df', palette=pal, size=5)
g.map(plt.scatter, "x", "y", s=50, alpha=.7,
linewidth=.5,
facecolors = 'none',
edgecolor=['red', 'blue'])
markers = [plt.Line2D([0,0],[0,0], markeredgecolor=pal[key],
marker='o', markerfacecolor='none',
mew=0.3,
linestyle='')
for key in pal]
plt.legend(markers, pal.keys(), numpoints=1, title="cat")
plt.show()
结果如下:
原则上,您应该能够使用 fillstyle="none"
创建一个圆形标记,但那里有一些 deep complications,但它目前无法像您希望的那样工作。
最简单的纯 seaborn 解决方案是利用您可以使用任意乳胶符号作为标记这一事实:
sns.scatterplot(data=df, x='x', y='y', hue="cat", marker="$\circ$", ec="face", s=100)
这有点受限,因为您无法控制圆的厚度。
混合 seaborn-matplotlib 方法更灵活,但也更麻烦(您需要自己创建图例):
palette = {"a": "C0", "b": "C1"}
kws = {"s": 70, "facecolor": "none", "linewidth": 1.5}
ax = sns.scatterplot(
data=df, x='x', y='y',
edgecolor=df["cat"].map(palette),
**kws,
)
handles, labels = zip(*[
(plt.scatter([], [], ec=color, **kws), key) for key, color in palette.items()
])
ax.legend(handles, labels, title="cat")
第三个选项是使用 FacetGrid
。这不太灵活,因为情节必须在它自己的图中。但这相当简单;另一个答案使用 FacetGrid
但它有点过度设计,因为它忘记了 hue_kws
参数:
palette = ["C0", "C1"]
g = sns.FacetGrid(
data=df, hue="cat",
height=4, aspect=1.25,
hue_kws={"edgecolor": palette},
)
g.map(plt.scatter, "x", "y", facecolor="none", lw=1.5)
g.add_legend()
有时*,退回到 matplotlib 功能更容易:
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'x': [3,2,5,2,1,0],
'y': [1,1,2,3,0,2],
'cat': ['a','a','a','b','b','b']})
fig, ax = plt.subplots()
m_colors = ["blue", "tab:orange", "red", "green"]
for (cat, group), col in zip(df.groupby("cat"), m_colors):
ax.scatter(group.x, group.y, edgecolors=col, facecolors="none", alpha=0.7, label=cat)
ax.legend(title="empty circles")
plt.show()
示例输出:
*seaborn 和 pandas 非常适合他们提供的东西。但我看到很多例子,人们认为“这很简单,所以简单地添加 XYZ 功能应该很容易”,然后最终得到复杂的代码,如果他们首先在基础 matplotlib 中编写代码会简单得多地方。
基于类似的问题 (),这里有一个很好的新方法来处理这个问题:
首先,定义你的颜色图。其次,设置合适的色调并在 palette 和 edgecolor 参数中指定颜色图。
penguins = sns.load_dataset("penguins")
colormap = {"Adelie": "purple", "Chinstrap": "orange", "Gentoo": "green"}
sns.jointplot(
data=penguins,
x="bill_length_mm",
y="bill_depth_mm",
hue="species",
palette=colormap,
ec=penguins["species"].map(colormap),
fc="none",
)
如何使用 Seaborn 散点图将标记设置为空心圆而不是实心圆?
这是一个简单的例子:
import pandas as pd
import seaborn as sns
df = pd.DataFrame(
{'x': [3,2,5,1,1,0],
'y': [1,1,2,3,0,2],
'cat': ['a','a','a','b','b','b']}
)
sns.scatterplot(data=df, x='x', y='y', hue='cat')
我尝试了以下方法但没有成功;其中大部分不会抛出错误,而是产生与上面相同的图。我认为这些不起作用,因为颜色是使用 hue
参数设置的,但我不确定修复方法是什么。
sns.scatterplot(data=df, x='x', y='y', hue='cat', facecolors = 'none')
sns.scatterplot(data=df, x='x', y='y', hue='cat', facecolors = None)
sns.scatterplot(data=df, x='x', y='y', hue='cat', markerfacecolor = 'none')
sns.scatterplot(data=df, x='x', y='y', hue='cat', markerfacecolor = None)
with sns.plotting_context(rc={"markerfacecolor": None}):
sns.scatterplot(data=df, x='x', y='y', hue='cat')
我使用 seaborn.FacetGrid
修改了您的代码,如下所示(基于 @cphlewis 此处提供的
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
x1 = [3,2,5]
y1 = [1,1,2]
x2 = [1,1,0]
y2 = [3,0,2]
df1 = pd.DataFrame({'x1':x1, 'y1':y1})
df2 = pd.DataFrame({'x2':x2, 'y2':y2})
df = pd.concat([df1.rename(columns={'x1':'x','y1':'y'})
.join(pd.Series(['a']*len(df1), name='df')),
df2.rename(columns={'x2':'x','y2':'y'})
.join(pd.Series(['b']*len(df2), name='df'))],
ignore_index=True)
pal = dict(a="blue", b="red")
g = sns.FacetGrid(df, hue='df', palette=pal, size=5)
g.map(plt.scatter, "x", "y", s=50, alpha=.7,
linewidth=.5,
facecolors = 'none',
edgecolor=['red', 'blue'])
markers = [plt.Line2D([0,0],[0,0], markeredgecolor=pal[key],
marker='o', markerfacecolor='none',
mew=0.3,
linestyle='')
for key in pal]
plt.legend(markers, pal.keys(), numpoints=1, title="cat")
plt.show()
结果如下:
原则上,您应该能够使用 fillstyle="none"
创建一个圆形标记,但那里有一些 deep complications,但它目前无法像您希望的那样工作。
最简单的纯 seaborn 解决方案是利用您可以使用任意乳胶符号作为标记这一事实:
sns.scatterplot(data=df, x='x', y='y', hue="cat", marker="$\circ$", ec="face", s=100)
这有点受限,因为您无法控制圆的厚度。
混合 seaborn-matplotlib 方法更灵活,但也更麻烦(您需要自己创建图例):
palette = {"a": "C0", "b": "C1"}
kws = {"s": 70, "facecolor": "none", "linewidth": 1.5}
ax = sns.scatterplot(
data=df, x='x', y='y',
edgecolor=df["cat"].map(palette),
**kws,
)
handles, labels = zip(*[
(plt.scatter([], [], ec=color, **kws), key) for key, color in palette.items()
])
ax.legend(handles, labels, title="cat")
第三个选项是使用 FacetGrid
。这不太灵活,因为情节必须在它自己的图中。但这相当简单;另一个答案使用 FacetGrid
但它有点过度设计,因为它忘记了 hue_kws
参数:
palette = ["C0", "C1"]
g = sns.FacetGrid(
data=df, hue="cat",
height=4, aspect=1.25,
hue_kws={"edgecolor": palette},
)
g.map(plt.scatter, "x", "y", facecolor="none", lw=1.5)
g.add_legend()
有时*,退回到 matplotlib 功能更容易:
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'x': [3,2,5,2,1,0],
'y': [1,1,2,3,0,2],
'cat': ['a','a','a','b','b','b']})
fig, ax = plt.subplots()
m_colors = ["blue", "tab:orange", "red", "green"]
for (cat, group), col in zip(df.groupby("cat"), m_colors):
ax.scatter(group.x, group.y, edgecolors=col, facecolors="none", alpha=0.7, label=cat)
ax.legend(title="empty circles")
plt.show()
示例输出:
*seaborn 和 pandas 非常适合他们提供的东西。但我看到很多例子,人们认为“这很简单,所以简单地添加 XYZ 功能应该很容易”,然后最终得到复杂的代码,如果他们首先在基础 matplotlib 中编写代码会简单得多地方。
基于类似的问题 (
首先,定义你的颜色图。其次,设置合适的色调并在 palette 和 edgecolor 参数中指定颜色图。
penguins = sns.load_dataset("penguins")
colormap = {"Adelie": "purple", "Chinstrap": "orange", "Gentoo": "green"}
sns.jointplot(
data=penguins,
x="bill_length_mm",
y="bill_depth_mm",
hue="species",
palette=colormap,
ec=penguins["species"].map(colormap),
fc="none",
)