2016-12-24 7 views
4

seabornプロット(具体的にはkdeplot)をクリップするのに問題があります。this example in the 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) 

結果:

enter image description here

IはKDE輪郭線が外部に表示されないように、この結果をクリップしたいです円の私はそれまでこれを行う方法を見つけていない...これは可能ですか?

答えて

1

セレニティの答えは単純な形状のために動作しますが、形状は(私も、難易度の正確なパラメータを確立していた)以上3かそこらの頂点が含まれている場合、未知の理由のために分解します。十分に大きな形状の場合、塗りつぶしはエッジがどこにあるのか、as for example hereに流れます。

しかし私は正しい道に沿って考えました。 matplotlibネイティブを使って単純に行うことはできませんが(とにかく彼が提供したコードには誤りがありますか?)、これはshapelyライブラリを使用すると簡単です。これはこのようなタスクのためのものです。あなたは見栄えのsymmetric_difference方法が必要になります。この場合、形状

を生成

symmetric differenceは、この切り抜き操作のために設定された理論名です。

この例では、マンハッタン型ポリゴンをshapely.geometry.Polygonオブジェクトとしてロードしました。ここで初期化プロセスを隠すことはしませんし、簡単に行うことができます。

manhattan.envelopeを使用してmanhattanの周囲にボックスを描き、その差を適用することができます。

に私たちを取得するどの行う
unmanhattan = manhattan.envelope.symmetric_difference(manhattan) 

:これは次のようであるプロット

[OK]をにそれを追加する

enter image description here

が、これはないmatplotlibPatchshapelyオブジェクトでありますそれをプロットにどのように追加するのですか? 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) 

とget:

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()'を追加する)がこのコードを破って元の結果に戻すことに注意してください。これは 'facecolor'が実行時に' seaborn'スタイルの(完全に透明な)元のスタイルと '(1,1,1,1)'で '(1,1,1,0)であるためです。後者を手動で固定することで問題が解決されます。 –

+0

このソリューションは、より複雑な形状で動作するように拡張できますか? 3つ以上の面を持つポリゴンの場合、コードはそのままでは失敗します。次の画像は何が起こるかを示しています:この場合は 'facecolor = 'yellow''の間に' edgecolor =' steelblue''ですが、あなたが見ることができるようにanti-shapeは何とかそれを飲み込むように見えます:http:// i。 imgur.com/gS5v8dk.png。 –

関連する問題