Seaborn在子图中生成单独的图形。

12

我试图使用以下代码在seaborn中制作2x1的子图:

```python import seaborn as sns import matplotlib.pyplot as plt
fig, axs = plt.subplots(nrows=2, ncols=1)
sns.lineplot(x=x_data, y=y_data, ax=axs[0]) sns.scatterplot(x=x_data, y=y_data, ax=axs[1]) plt.show() ```

data = pandas.DataFrame({"x": [1, 2, 4],
                        "y": [10,20,40],
                        "s": [0.01,0.1,1.0]})

plt.figure()
plt.subplot(2, 1, 1)
sns.pointplot(x="x", y="y", data=data)
plt.errorbar(np.arange(len(data["x"])), data["y"], yerr=data["s"])
plt.subplot(2, 1, 2)
sns.factorplot(x="x", y="y", data=data)
plt.show()

它会产生两个单独的图形,而不是一个包含两个子图的图形。为什么会这样?如何使seaborn可以多次调用以创建单独的子图?

我尝试查看下面引用的文章,但我无法看到即使首先调用factorplot,也可以添加子图的方法。有人能展示一个例子吗?这会非常有帮助。这是我的尝试:

data = pandas.DataFrame({"x": [1, 2, 4],
                        "y": [10,20,40],
                        "s": [0.01,0.1,1.0]})

fig = plt.figure()
sns.pointplot(x="x", y="y", data=data)
ax = sns.factorplot(x="x", y="y", data=data)
fig.add_subplot(212, axes=ax)
plt.errorbar(np.arange(len(data["x"])), data["y"], yerr=data["s"])
plt.show()

@mwaskom:我看到了,但是不知道它如何回答问题,因为“factorplot”没有使用“ax=”参数。听起来这是不可能的吗?我想在子图中获得 seaborn “factorplot”的美观效果。 - lgd
1个回答

19
问题在于factorplot创建了一个新的FacetGrid实例(进而创建了自己的图形),它将应用一个绘图函数(默认情况下是pointplot)。因此,如果您只想要pointplot,那么使用pointplot而不是factorplot就有意义。
以下是一种方法,如果您真的希望出于某种原因告诉factorplot在哪个Axes上进行绘图,那么可以使用以下技巧。正如@mwaskom在评论中指出的那样,这不是一种受支持的行为,因此尽管它现在可能有效,但未来可能会失效。
您可以使用ax关键字参数告诉factorplot在给定的Axes上绘制,该参数会向下传递到matplotlib,因此链接的答案确实回答了您的查询。然而,它仍然会因为factorplot调用而创建第二个图形,但是该图形将是空的。这里的解决方法是在调用plt.show()之前关闭那个额外的图形。
例如:
import matplotlib.pyplot as plt
import pandas
import seaborn as sns
import numpy as np

data = pandas.DataFrame({"x": [1, 2, 4],
                        "y": [10,20,40],
                        "s": [10,10,10]}) # I increased your errors so I could see them

# Create a figure instance, and the two subplots
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

# Tell pointplot to plot on ax1 with the ax argument
sns.pointplot(x="x", y="y", data=data, ax=ax1)

# Plot the errorbar directly on ax1
ax1.errorbar(np.arange(len(data["x"])), data["y"], yerr=data["s"])

# Tell the factorplot to plot on ax2 with the ax argument
# Also store the FacetGrid in 'g'
g=sns.factorplot(x="x", y="y", data=data, ax=ax2)

# Close the FacetGrid figure which we don't need (g.fig)
plt.close(g.fig)

plt.show()

enter image description here


2
这个“有效”,是因为factorplot通过它的kwargs传递参数,所以ax参数到了正确的位置,但这种行为并不被支持,我不会依赖它。 - mwaskom
@mwaskom,同意,但你知道更好的方法吗?只是觉得现在这可能有用。 - tmdavison
3
有一个基本的混淆。 factorplot 只是将一个绘图函数(默认为 pointplot)应用于由 FacetGrid 管理的子图网格上。尝试在现有的子图上绘制 factorplot 毫无意义。只需使用 pointplot 即可。 - mwaskom
@mwaskom:但是factorplot做了一些非常有用的事情,pointplot没有做到:它可以从你的df中读取标签并生成一个pointplot。对于pointplot,我需要手动完成这个过程。拥有一个像pointplot一样接受kwargs参数(如“hue”)并从数据框中读取值的函数将非常有用,因为它可以在不将整个图形控制权交给factorplot的情况下使用。它在单独的子图中非常有用。 - lgd
2
我真的不确定你的意思。在单个子图中,factorplot所做的任何事情,pointplot都可以做到,因为factorplot实际上只是在每个轴上调用pointplot - mwaskom

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