2016-12-24 68 views
4

我有麻煩削波seaborn圖(一kdeplot,特別是)因爲我以爲會是每this example in the matplotlib docs相當簡單的剪輯。設置在seaborn情節

例如,下列代碼:

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) 

結果在下面的輸出:

enter image description here

我想使得KDE輪廓線不會出現外剪裁此結果的圈子。到目前爲止,我還沒有找到辦法做到這一點......這可能嗎?

回答

1

平靜的回答適用於簡單的形狀,但打破了,原因不明時形狀包含超過3個左右的頂點(我有困難建立的確切參數,偶數)。對於足夠大的形狀,填充物流入邊緣應該在的位置,as for example here

它確實讓我沿着正確的路徑思考,但是。儘管使用matplotlib原生程序(可能是他提供的代碼中存在錯誤?)似乎不可能這樣做,但使用shapely庫時很容易,這對於像這樣的任務是非常有用的。

生成形狀

在這種情況下,你需要勻稱的symmetric_difference方法。 A symmetric difference是此切出操作的集合理論名稱。

對於這個例子中我已經加載曼哈頓形多邊形作爲shapely.geometry.Polygon對象。我不會在這裏隱藏初始化過程,這很容易做到,並且你期望它是一切。

我們可以使用manhattan.envelope圍繞我們的manhattan繪製一個框,然後應用差異。這是如下:

unmanhattan = manhattan.envelope.symmetric_difference(manhattan) 

否則它獲取我們:

enter image description here

它添加到情節

好了,但是這是一個shapely對象不是matplotlibPatch ,我們如何將它添加到情節? 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) 

並獲得:

enter image description here

而與此延伸至多邊形的視圖(紐約市),其餘一點點更多的工作,我們可以得到下面的最終結果:

enter image description here

1

我想你的例子只適用於'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() 

enter image description here

+0

這超出了巧妙而在巫術觸動!請注意,一個非常小的改變(在這種情況下,添加'sns.reset_orig()',我需要))打破這個代碼並返回到我們原來的結果;這是因爲在原始樣式(完全透明)和''seaborn'樣式的'(1,1,1,1)'中,'facecolor'在運行時爲'(1,1,1,0)'。手動修復後者可解決問題。 –

+0

該解決方案可以擴展到更復雜的形狀嗎?如果多邊形的邊長超過三條,代碼就會失敗。下圖顯示了發生了什麼:在這種情況下'facecolor ='yellow'' while'edgecolor ='steelblue'',但正如你所看到的反形狀似乎吞嚥自己(?)莫名其妙:http://我。 imgur.com/gS5v8dk.png。 –