I am having trouble clipping a seaborn
plot (a kdeplot
, specifically) as I thought would be fairly simple per this example in the matplotlib
docs.
For example, the following code:
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)
Results in the following output:
I would like to clip this result so that the KDE contour lines do not appear outside of the circle. I haven't found a way to do it thus far...is this possible?
Serenity's answer works for simple shapes, but breaks down for reasons unknown when the shape contains more than three or so vertices (I had difficulty establishing the exact parameters, even). For sufficiently large shapes the fill flows into where the edge should be, as for example here.
It did get me thinking along the right path, however. While it doesn't seem to be possible to do so simply using matplotlib
natives (perhaps there's an error in the code he provided anyway?), it's easy as pie when using the shapely
library, which is meant for tasks like this one.
Generating the Shape
In this case you will need shapely's symmetric_difference
method. A symmetric difference is the set theoretic name for this cut-out operation.
For this example I've loaded a Manhattan-shaped polygon as a shapely.geometry.Polygon
object. I won't covert the initialization process here, it's easy to do, and everything you expect it to be.
We can draw a box around our manhattan
using manhattan.envelope
, and then apply the difference. This is the following:
unmanhattan = manhattan.envelope.symmetric_difference(manhattan)
Doing which gets us to:
Adding it to the Plot
Ok, but this is a shapely
object not a matplotlib
Patch
, how do we add it to the plot? The descartes
library handles this conversion.
unmanhattan_patch = descartes.PolygonPatch(unmanhattan)
This is all we need! Now we do:
unmanhattan_patch = descartes.PolygonPatch(unmanhattan)
ax.add_patch(unmanhattan_patch)
sns.kdeplot(x=points['x_coord'], y=points['y_coord'], ax=ax)
And get:
And with a little bit more work extending this to the rest of the polygons in the view (New York City), we can get the following final result:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With