How to fill area under step curve using pyplot? - python-3.x

I have plotted two step curves using pyplot.step(), and I would like to shade in the area beneath these curves (ideally with transparent shading). pyplot.fill_between() assumes linear interpolation, whereas I want to see step interpolation, as displayed below:
How can I shade in the region beneath these curves? Transparent coloring would be great, as this would make clear where these curves overlap.

You can use the alpha value of the fill_between to make it semi-transparent.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,50,35)
y = np.random.exponential(1, len(x))
y2 = np.random.exponential(1, len(x))
plt.fill_between(x,y, step="pre", alpha=0.4)
plt.fill_between(x,y2, step="pre", alpha=0.4)
plt.plot(x,y, drawstyle="steps")
plt.plot(x,y2, drawstyle="steps")
plt.show()

Related

Seaborn, how to gradient color distplot depending on the x-axis value

I'd like to gradient-color the plot line in the Seaborn's distplot, depending on the x-axis value. For example if the value is 1, then the colour is blue, when 1.1 then it's blue and goes toward green, and so on, and so on. For example like on the plot-draft below:
The problem is, that I don't how to set colour map manually in Seaborn or how to force x-dependend coloring of the plot's curve.
Note that distplot has been deprecated. In the current seaborn version, kdeplot draws a kde curve.
You can grab the generated line with ax.get_lines(). And then create a multicolored line similar to this tutorial example.
Here is some code to demonstrate the idea (currently it would also still work with distplot):
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import seaborn as sns
import numpy as np
np.random.seed(1234)
data = np.random.uniform(-1, 1.1, (5, 1000)).cumsum(axis=1).ravel()
ax = sns.kdeplot(x=data)
x, y = ax.get_lines()[0].get_data()
segments = np.array([x[:-1], y[:-1], x[1:], y[1:]]).T.reshape(-1, 2, 2)
norm = plt.Normalize(x.min(), x.max())
lc = LineCollection(segments, cmap='turbo_r', norm=norm)
lc.set_array(x[:-1])
lc.set_linewidth(2)
ax.get_lines()[0].remove()
line = ax.add_collection(lc)
ax.fill_between(x, y, color='purple', alpha=0.1, hatch='xx')
ax.margins(x=0)
ax.set_ylim(ymin=0)
plt.show()

What kind of plot from matplotlib should I use?

I am programming in Python 3 and I have data structured like this:
coordinates = [(0.15,0.25),(0.35,0.25),(0.55,0.45),(0.65,0.10),(0.15,0.25)]
These are coordinates. Within each pair, the first number is the x coordinate and the second one the y coordinate. Some of the coordinates repeat themselves. I want to plot these data like this:
The coordinates that are most frequently found should appear either as higher intensity (i.e., brighter) points or as points with a different color (for example, red for very frequent coordinates and blue for very infrequent coordinates). Don't worry about the circle and semicircle. That's irrelevant. Is there a matplotlib plot that can do this? Scatter plots do not work because they do not report on the frequency with which each coordinate is found. They just create a cloud.
The answer is:
import matplotlib.pyplot as plt
from scipy.stats import kde
import numpy as np
xvalues = np.random.normal(loc=0.5,scale=0.01,size=50000)
yvalues = np.random.normal(loc=0.25,scale=0.1,size=50000)
nbins=300
k = kde.gaussian_kde([xvalues,yvalues])
xi, yi = np.mgrid[0:1:nbins*1j,0:1:nbins*1j]
zi = k(np.vstack([xi.flatten(),yi.flatten()]))
fig, ax = plt.subplots()
ax.pcolormesh(xi, yi, zi.reshape(xi.shape), shading='auto', cmap=plt.cm.hot)
x = np.arange(0.0,1.01,0.01,dtype=np.float64)
y = np.sqrt((0.5*0.5)-((x-0.5)*(x-0.5)))
ax.axis([0,1,0,0.55])
ax.set_ylabel('S', fontsize=16)
ax.set_xlabel('G', fontsize=16)
ax.tick_params(labelsize=12, width=3)
ax.plot(x,y,'w--')
plt.show()

How to change seaborn jointplot linewidth?

hexs = sns.jointplot(a,b,marker = '.', kind = "reg", height=1.476, scatter_kws={'s':2, 'linewidth':0.1},joint_kws={'line_kws':{'linewidth':'0.5'}})
I can change the scatter size and the regression line width.
but how can I change the curve width ?(the curve pointed by the black arrow)
As the name indicates, a jointplot is a combination of some other plots.
The visual aspect of the marginal subplots can be controlled via marginal_kws=.
In this case, the marginal plots are drawn using distplot. On its turn, in a distplot, the kernel density approximation is drawn with kdeplot. The parameters of this kdeplot are controlled via the kde_kws inside the marginal_kws.
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
g = sns.jointplot("total_bill", "tip", data=tips, marker='.', kind="reg", height=1.476,
scatter_kws={'s': 2, 'linewidth': 0.1},
joint_kws={'line_kws': {'linewidth': 0.5}},
marginal_kws={'color': 'g', 'kde_kws': {'linewidth': 0.5}})
plt.show()

How to plot fill_betweenx to fill the area between y1 and y2 with different scales using matplotlib.pyplot?

I am trying to fill the area between two vertical curves(RHOB and NPHI) using matplotlib.pyplot. Both RHOB and NPHI are having different scale of x-axis.
But when i try to plot i noticed that the fill_between is filling the area between RHOB and NPHI in the same scale.
#well_data is the data frame i am reading to get my data
#creating my subplot
fig, ax=plt.subplots(1,2,figsize=(8,6),sharey=True)
ax[0].get_xaxis().set_visible(False)
ax[0].invert_yaxis()
#subplot 1:
#ax01 to house the NPHI curve (NPHI curve are having values between 0-45)
ax01=ax[0].twiny()
ax01.set_xlim(-15,45)
ax01.invert_xaxis()
ax01.set_xlabel('NPHI',color='blue')
ax01.spines['top'].set_position(('outward',0))
ax01.tick_params(axis='x',colors='blue')
ax01.plot(well_data.NPHI,well_data.index,color='blue')
#ax02 to house the RHOB curve (RHOB curve having values between 1.95,2.95)
ax02=ax[0].twiny()
ax02.set_xlim(1.95,2.95)
ax02.set_xlabel('RHOB',color='red')
ax02.spines['top'].set_position(('outward',40))
ax02.tick_params(axis='x',colors='red')
ax02.plot(well_data.RHOB,well_data.index,color='red')
# ax03=ax[0].twiny()
# ax03.set_xlim(0,50)
# ax03.spines['top'].set_position(('outward',80))
# ax03.fill_betweenx(well_data.index,well_data.RHOB,well_data.NPHI,alpha=0.5)
plt.show()
ax03=ax[0].twiny()
ax03.set_xlim(0,50)
ax03.spines['top'].set_position(('outward',80))
ax03.fill_betweenx(well_data.index,well_data.RHOB,well_data.NPHI,alpha=0.5)
above is the code that i tried, but the end result is not what i expected.
it is filling area between RHOB and NPHI assuming RHOB and NPHI is in the same scale.
How can i fill the area between the blue and the red curve?
Since the data are on two different axes, but each artist needs to be on one axes alone, this is hard. What would need to be done here is to calculate all data in a single unit system. You might opt to transform both datasets to display-space first (meaning pixels), then plot those transformed data via fill_betweenx without transforming again (transform=None).
import numpy as np
import matplotlib.pyplot as plt
y = np.linspace(0, 22, 101)
x1 = np.sin(y)/2
x2 = np.cos(y/2)+20
fig, ax1 = plt.subplots()
ax2 = ax1.twiny()
ax1.tick_params(axis="x", colors="C0", labelcolor="C0")
ax2.tick_params(axis="x", colors="C1", labelcolor="C1")
ax1.set_xlim(-1,3)
ax2.set_xlim(15,22)
ax1.plot(x1,y, color="C0")
ax2.plot(x2,y, color="C1")
x1p, yp = ax1.transData.transform(np.c_[x1,y]).T
x2p, _ = ax2.transData.transform(np.c_[x2,y]).T
ax1.autoscale(False)
ax1.fill_betweenx(yp, x1p, x2p, color="C9", alpha=0.4, transform=None)
plt.show()
We might equally opt to transform the data from the second axes to the first. This has the advantage that it's not defined in pixel space and hence circumvents a problem that occurs when the figure size is changed after the figure is created.
x2p, _ = (ax2.transData + ax1.transData.inverted()).transform(np.c_[x2,y]).T
ax1.autoscale(False)
ax1.fill_betweenx(y, x1, x2p, color="grey", alpha=0.4)

Equivalent of pcolormesh for irregular points

I am using pcolormesh on a 2-D NumPY array of points M, so
pcolormesh(X,Y,M)
plots a grid of colors where the X-axis range labels correspond to X[i], Y-axis range labels correspond to Y[j], and the color plotted at point (i,j) corresponds to the level of M[i,j].
I would also like to plot the same thing but where I have a 1-D array M[i], and the color plotted at point (X[i], Y[i]) corresponds to the level of M[i].
I don't see any out of the box solution for this in matplotlib. Is there one? This is the closest I could come up with, taking a cue from an answer to this question:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def intensityplot(x,y,z):
z=z/z.max()
colors = cm.rainbow(z)
for X,Y,Z in zip(x,y,colors):
plt.scatter([X],[Y], color=Z)

Resources