numpy and matplotlib : Integration inside contour in a 2D plot - numpy

I have a function : z=f(x,y) and I draw a contour plot.
For example :
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
x=np.linspace(0,10,11)
y=np.linspace(0,10,11)
X,Y=np.meshgrid(x,y)
Z=(X+4)*(X-14)*(Y+6)*(Y-14)/1000
fig, ax =plt.subplots()
CS= ax.contour(x,x,Z,[7],colors='black')
ax.clabel(CS, inline=True, fontsize=10)
From the contour path data points (CS.collections[0].get_paths()[0]), how is it possible to integrate z inside this area ?
Thanks for answer.

Related

Data Points not fully shown Seaborn

import matplotlib.pyplot as plt
import seaborn as sb
from matplotlib import style
style.use("dark_background")
tips = sb.load_dataset("tips")
plt.figure(figsize=(8,4))
sb.set_context('paper', font_scale=1.2)
sb.lmplot(x="total_bill", y="tip", hue="sex", data=tips,markers=['o', '^'],
scatter_kws={'s':50, "linewidth" : 0.2, "edgecolor" : 'w'}, aspect=1.5)
I am using dataset tips(seaborn dataset). When am plotting the graph some data points are not fully shown like one at (0,1) the triangle data point is not fully shown and other at (51,10) the circle data point is half visible.
Graph : Graph Image
Where am I doing wrong?
In addition to the correct answer by #r-beginners, you can pass clip_on=False to the plotting function to prevent artists to being clipped at the edge of the axes.
sb.lmplot(x="total_bill", y="tip", hue="sex", data=tips,markers=['o', '^'],
scatter_kws={'s':50, "linewidth" : 0.2, "edgecolor" : 'w', 'clip_on':False}, aspect=1.5)
You can use ax.set_xlim() in such a case. You can use ax.set_xlim() to expand the area over which the image is displayed. Also, seaborn gives priority to height and aspect ratio over figsize.
import matplotlib.pyplot as plt
import seaborn as sb
from matplotlib import style
style.use("dark_background")
tips = sb.load_dataset("tips")
# plt.figure(figsize=(8,4))
sb.set_context('paper', font_scale=1.2)
sb.lmplot(x="total_bill", y="tip", hue="sex", data=tips,markers=['o', '^'],
scatter_kws={'s':50, "linewidth" : 0.2, "edgecolor" : 'w'}, aspect=2, legend_out=False, height=4)
ax = plt.gca()
ax.set_xlim((0,55))

Making sure 0 gets white in a RdBu colorbar

I create a heatmap with the following snippet:
import numpy as np
import matplotlib.pyplot as plt
d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu)
plt.colorbar()
plt.show()
The result is plot below:
Now, since the middle point of the data is not 0, the cells in which the colormap has value 0 are not white, but rather a little reddish.
How do I force the colormap so that max=blue, min=red and 0=white?
Use a DivergingNorm.
Note: From matplotlib 3.2 onwards DivergingNorm is renamed to TwoSlopeNorm.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
d = np.random.normal(.4,2,(10,10))
norm = mcolors.DivergingNorm(vmin=d.min(), vmax = d.max(), vcenter=0)
plt.imshow(d, cmap=plt.cm.RdBu, norm=norm)
plt.colorbar()
plt.show()
A previous SO post (Change colorbar gradient in matplotlib) wanted a solution for a more complicated situation, but one of the answers talked about the MidpointNormalize subclass in the matplotlib documentation. With that, the solution becomes:
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
class MidpointNormalize(mpl.colors.Normalize):
## class from the mpl docs:
# https://matplotlib.org/users/colormapnorms.html
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
super().__init__(vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu,norm=MidpointNormalize(midpoint=0))
plt.colorbar()
plt.show()
Kudos to Joe Kington for writing the subclass, and to Rutger Kassies for pointing out the answer.

matplotlib pyplot pcolor savefig colorbar transparency

I am trying to export a pcolor figure with a colorbar.
The cmap of the colorbar has a transparent color.
The exported figure has transparent colors in the axes but not in the colorbar. How can I fix this?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
x = np.random.random((10, 10))
colors = [(0,0,0,0), (0,0,0,1)]
cm = LinearSegmentedColormap.from_list('custom', colors, N=256, gamma=0)
plt.pcolor(x,cmap=cm)
plt.colorbar()
plt.savefig('figure.pdf',transparent=True)
I put the image against a grey background to check. As can be seen, the cmap in the axes is transparent while the one in the colorbar is not.
While the colorbar resides inside an axes, it has an additional background patch associated with it. This is white by default and will not be taken into account when transparent=True is used inside of savefig.
A solution is hence to remove the facecolor of this patch manually,
cb.patch.set_facecolor("none")
A complete example, which shows this without actually saving the figure
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
x = np.random.random((10, 10))
colors = [(1,1,1,0), (0,0,0,1)]
cm = LinearSegmentedColormap.from_list('custom', colors, N=256, gamma=0)
fig, ax = plt.subplots(facecolor="grey")
im = ax.pcolor(x,cmap=cm)
cb = fig.colorbar(im, drawedges=False)
ax.set_facecolor("none")
cb.patch.set_facecolor("none")
plt.show()

draw artists over seaborn facetGrid

I would like to draw arrows over all panels of a facetGrid.
In this dummy example, I want to draw the same arrow on all panels:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pylab as plt
datDf=pd.DataFrame({'values':np.random.randint(0,100,100)})
datDf['group']=np.random.randint(0,5,100)
g = sns.FacetGrid(datDf, col="group",
col_wrap=3,
size=4.5,
sharex=True, sharey=True, despine=False)
g.map(plt.plot,'values')
for ax in g.axes:
arrow=plt.arrow(0,0,50,50,width=5,
length_includes_head=True,
head_width=5*2,
color='gray')
ax.add_artist(arrow)
I am receiving this error:
ValueError: Can not reset the axes. You are probably trying to re-use an artist in more than one Axes which is not supported
What is the correct way to draw artists on facetGrids?
You can use ax.arrow instead of plt.arrow to draw an arrow on the axes.
This should work:
for ax in g.axes:
ax.arrow(0,0,50,50,width=5,
length_includes_head=True,
head_width=5*2,
color='gray')

Control gridline spacing in seaborn

I'd like to change the spacing of the horizontal grid lines on a seaborn chart, I've tried setting the style with no luck:
seaborn.set_style("whitegrid", {
"ytick.major.size": 0.1,
"ytick.minor.size": 0.05,
'grid.linestyle': '--'
})
bar(range(len(data)),data,alpha=0.5)
plot(avg_line)
The gridlines are set automatically desipite me trying to overide the tick size
Any suggestions? Thanks!
you can set the tick locations explicitly later, and it will draw the grid at those locations.
The neatest way to do this is to use a MultpleLocator from the matplotlib.ticker module.
For example:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
sns.set_style("whitegrid", {'grid.linestyle': '--'})
fig,ax = plt.subplots()
ax.bar(np.arange(0,50,1),np.random.rand(50)*0.016-0.004,alpha=0.5)
ax.yaxis.set_major_locator(ticker.MultipleLocator(0.005))
plt.show()
The OP asked about modifying tick distances in Seaborn.
If you are working in Seaborn and you use a plotting feature that returns an Axes object, then you can work with that just like any other Axes object in matplotlib. For example:
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
from matplotlib.ticker import MultipleLocator
df = sm.datasets.get_rdataset("Guerry", "HistData").data
ax = sns.scatterplot('Literacy', 'Lottery', data=df)
ax.yaxis.set_major_locator(MultipleLocator(10))
ax.xaxis.set_major_locator(MultipleLocator(10))
plt.show()
Put if you are working with one of the Seaborn processes that involve FacetGrid objects, you will see precious little help on how to modify the tick marks without manually setting them. You have dig out the Axes object from the numpy array inside FacetGrid.axes .
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.ticker import MultipleLocator
tips = sns.load_dataset("tips")
g = sns.lmplot(x="total_bill", y="tip", hue="smoker", data=tips, )
g.axes[0][0].yaxis.set_major_locator(MultipleLocator(3))
Note the double subscript required. g is a FacetGrid object, which holds a two-dimensional numpy array of dtype=object, whose entries are matplotlib AxesSubplot objects.
If you are working with a FacetGrid that has multiple axes, then each one will have to be extracted and modified.