繁体   English   中英

在海洋图上设置剪辑

[英]Setting a clip on a seaborn plot

我在裁剪seaborn (特别是kdeplot )时遇到了麻烦,因为我认为matplotlib docs中的每个示例都非常简单。

例如,以下代码:

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

fig = plt.figure()
ax = fig.add_subplot(111, frameon=False, xticks=[], yticks=[])

random_points = np.array([p for p in np.random.random(size=(100, 2)) if 0 < p[0] < 1 and 0 < p[1] < 1])

kde = sns.kdeplot(random_points[:,0], random_points[:,1], ax=ax)

xmin, xmax = kde.get_xlim()
ymin, ymax = kde.get_ylim()

patch = mpl.patches.Circle(((xmin + xmax)/2, (ymin + ymax) / 2), radius=0.4)
ax.add_patch(patch)
kde.set_clip_path(patch)

结果如下:

在此处输入图片说明

我想剪辑此结果,以使KDE轮廓线不会出现在圆之外。 到目前为止,我还没有找到一种方法...这可能吗?

Serenity的答案适用于简单的形状,但是当形状包含三个以上左右的顶点时(由于我甚至很难建立确切的参数),由于不明的原因而无法解决。 对于足够大的形状,填充物流入边缘应位于的位置, 例如此处

但是,这确实让我思考了正确的道路。 虽然似乎不可能仅使用matplotlib来做到这一点(无论他提供的代码中是否有错误?),但在使用shapely库时就很容易做到这一点,这适用于此类任务。

产生形状

在这种情况下,您将需要shapely的symmetric_difference方法。 对称差异是此切除操作的设定理论名称。

在此示例中,我已将曼哈顿形多边形加载为shapely.geometry.Polygon对象。 我不会在这里介绍初始化过程,这很容易做到,而且您期望的一切都将如此。

我们可以使用manhattan.envelopemanhattan周围绘制一个框,然后应用差异。 这是以下内容:

unmanhattan = manhattan.envelope.symmetric_difference(manhattan)

这样做使我们能够:

在此处输入图片说明

将其添加到绘图中

好的,但这是一个shapely对象,而不是matplotlib Patch ,我们如何将其添加到绘图中? descartes库处理此转换。

unmanhattan_patch = descartes.PolygonPatch(unmanhattan)

这就是我们所需要的! 现在我们做:

unmanhattan_patch = descartes.PolygonPatch(unmanhattan)
ax.add_patch(unmanhattan_patch)
sns.kdeplot(x=points['x_coord'], y=points['y_coord'], ax=ax)

得到:

在此处输入图片说明

并通过更多工作将其扩展到视图中的其余多边形(纽约市),我们可以得到以下最终结果:

在此处输入图片说明

我想您的示例仅适用于“ imshow”。

要隐藏圆上的轮廓线,必须绘制所需颜色的“反”多边形。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import seaborn as sns

# Color plot except polygon
def mask_outside(poly_verts, facecolor = None, ax = None):
    from matplotlib.patches import PathPatch
    from matplotlib.path import Path

    if ax is None: ax = plt.gca()
    if facecolor is None: facecolor = plt.gcf().get_facecolor()

    # Construct inverse polygon
    xlim, ylim = ax.get_xlim(), ax.get_ylim()
    bound_verts = [(xlim[0], ylim[0]), (xlim[0], ylim[1]), 
                   (xlim[1], ylim[1]), (xlim[1], ylim[0]), (xlim[0], ylim[0])]
    bound_codes = [Path.MOVETO] + (len(bound_verts) - 1) * [Path.LINETO]
    poly_codes = [Path.MOVETO] + (len(poly_verts) - 1) * [Path.LINETO]

    # Plot it
    path = Path(bound_verts + poly_verts, bound_codes + poly_codes)
    ax.add_patch(PathPatch(path, facecolor = facecolor, edgecolor = 'None', zorder = 1e+3))

# Your example
fig = plt.figure()
ax = fig.add_subplot(111, frameon=False, xticks=[], yticks=[])
random_points = np.array([p for p in np.random.random(size=(100, 2)) if 0 < p[0] < 1 and 0 < p[1] < 1])
kde = sns.kdeplot(random_points[:,0], random_points[:,1], ax=ax)

xmin, xmax = kde.get_xlim()
ymin, ymax = kde.get_ylim()

patch = mpl.patches.Circle(((xmin + xmax) / 2, (ymin + ymax) / 2), radius=0.4)
mask_outside([tuple(x) for x in patch.get_verts()]) # call before add_patch!
ax.add_patch(patch)

plt.show()

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM