[英]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.envelope
在manhattan
周圍繪制一個框,然后應用差異。 這是以下內容:
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.