Fill between standard deviations on Matplotlib lineplot - python

I have a line plot which graphs 2 columns of data loaded from an excel file. See Plot:
Matplotlib line plot
I want to display the standard deviation for each line (i.e., column of data) in my plot using the fill between function or something similar (like image 2), however I cannot figure out how to include this. Any help would be great. Please note that I am very new to this...
How I would like my plot to look
Here is the code used for my lineplot:
import pandas as pd
import scipy as sp
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
Probability_fast_gamma_on_theta = pd.read_excel(r'C:\Users\RL\Excel work\Probability_of_a_theta_cycle_containing_fast_gamma.xlsx')
fig5, ax5=plt.subplots()
plt.plot(Probability_fast_gamma_on_theta.MIA)
plt.plot(Probability_fast_gamma_on_theta.CTL)
plt.grid(False)
plt.ylim(0.0, 0.6)
plt.xlim(0.0, 25)
plt.legend(['MIA', 'CTL'], loc='lower right')
plt.show()

This is straightforwardly done using the plt.fill_between() function. A minimal example would be as follows:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.linspace(0, 2 * np.pi, 50)
y = np.sin(x) + np.random.randn(len(x)) * 0.03
yerr0 = y - (0.1 + np.random.randn(len(x)) * 0.03)
yerr1 = y + (0.1 + np.random.randn(len(x)) * 0.03)
ax.plot(x, y, color='C0')
plt.fill_between(x, yerr0, yerr1, color='C0', alpha=0.5)

Related

How to normalize colorbar in Python?

I want to adjust colobar scale from my current figure1 to the desired figure2 !!
My colorbar scale range is -1 to 1, but I want it in exponential form and for that I tried levels = np.linspace(-100e-2,100e-2) as well, but it also doesn't give the desired scale2
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
ds = xr.open_dataset('PL_Era_Tkt.nc')
wp = ds.w.mean(dim=['longitude','latitude']).plot.contourf(x='time',cmap='RdBu',add_colorbar=False,extend='both')
wpcb = plt.colorbar(wp)
wpcb.set_label(label='Pa.s${^{-1}}$',size=13)
plt.gca().invert_yaxis()
plt.title('Vertical Velocity',size=15)
My current scale
My desired scale
Since the data is not presented, I added normalized color bars with the data from the graph sample here. I think the color bar scales will also be in log format with this setup. Please note that the data used is not large, so I have not been able to confirm this.
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.ticker as ticker
import numpy as np
plt.style.use('seaborn-white')
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots()
ax.contourf(X, Y, Z, 20, cmap='RdGy')
cmap = mpl.cm.RdGy
norm = mpl.colors.Normalize(vmin=-1, vmax=1.0)
fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
ax=ax, orientation='vertical', label='Some Units', extend='both', ticks=ticker.LogLocator())
plt.show()

Plotting a gaussian fit to a histgram with displot or histplot

I've decided to give seaborn version 0.11.0 a go! Playing around with the displot function, which will replace distplot, as I understand it. I'm just trying to figure out how to plot a gaussian fit on to a histogram. Here's some example code.
import seaborn as sns
import numpy as np
x = np.random.normal(size=500) * 0.1
With distplot I could do:
sns.distplot(x, kde=False, fit=norm)
But how to go about it in displot or histplot?
So far the closest I've come to is:
sns.histplot(x,stat="probability", bins=30, kde=True, kde_kws={"bw_adjust":3})
But I think this just increases the smoothening of the plotted kde, which isn't exactly what I'm going for.
I really miss the fit parameter too. It doesn't appear they replaced that functionality when they deprecated the distplot function. Until they plug that hole, I created a short function to add the normal distribution overlay to my histplot. I just paste the function at the top of a file along with the imports, and then I just have to add one line to add the overlay when I want it.
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
def normal(mean, std, color="black"):
x = np.linspace(mean-4*std, mean+4*std, 200)
p = stats.norm.pdf(x, mean, std)
z = plt.plot(x, p, color, linewidth=2)
data = np.random.normal(size=500) * 0.1
ax = sns.histplot(x=data, stat="density")
normal(data.mean(), data.std())
If you would rather use stat="probability" instead of stat="density", you can normalize the fit curve with something like this:
def normal(mean, std, histmax=False, color="black"):
x = np.linspace(mean-4*std, mean+4*std, 200)
p = stats.norm.pdf(x, mean, std)
if histmax:
p = p*histmax/max(p)
z = plt.plot(x, p, color, linewidth=2)
data = np.random.normal(size=500) * 0.1
ax = sns.histplot(x=data, stat="probability")
normal(data.mean(), data.std(), histmax=ax.get_ylim()[1])
Sorry I am late to the party. Just check if this will meet your requirement.
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
data = np.random.normal(size=500) * 0.1
mu, std = norm.fit(data)
# Plot the histogram.
plt.hist(data, bins=25, density=True, alpha=0.6, color='g')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mu, std)
plt.plot(x, p, 'k', linewidth=2)
plt.show()

Matplotlib secondary_xaxis can't be formatted

I'm trying to get an "inverse" second x-axis to a x-axis in log-scale. secondary_xaxis works fine but I can't format the ticks as usually. Is this a bug or am I missing something?
Here's what I do:
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(figsize=(0.6*4,0.6*3))
y = np.random.rand(10)
x = np.linspace(30,200,num=10)
p = plt.plot(x, y, marker='o', markersize=3)
plt.xscale("log")
def m2rho(m):
return 1 / m * 1000
def rho2m(rho):
return 1 / rho / 1000
secax = axs.secondary_xaxis('top', functions=(m2rho, rho2m))
from matplotlib.ticker import ScalarFormatter, NullFormatter
for axis in [axs.xaxis, secax.xaxis]:
axis.set_major_formatter(ScalarFormatter())
axis.set_minor_formatter(NullFormatter())
axs.set_xticks([50, 100, 200])
secax.set_xticks([20,10,5])
plt.tight_layout()
plt.show()
Resulting in:
So essentially the second axis on top should display the ticks 20, 10 and 5 in non-scientific numbers, but it doesn't.

Reproduce two distributions as provided on a single plot using Python

I want to draw distributions like shown in figure below -- tail of distributions. I have tried following but not quite getting there:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab
import math
mean1 = 0
variance1 = 1
sigma1 = math.sqrt(variance1)
x = np.linspace(-3,3.5,100, endpoint=True)
plt.plot(x,mlab.normpdf(x,mean1,sigma1))
mean2 = 0.4
variance2 = 2
sigma2 = math.sqrt(variance2)
y = np.linspace(-4,3.5,100, endpoint=False)
plt.plot(x,mlab.normpdf(y,mean2,sigma2))
##plt.axis('off')
plt.yticks([])
plt.xticks([])
plt.show()
Any suggestions would be appreciative?
You want fill_between:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab
import math
mean1 = 0
variance1 = 1
sigma1 = math.sqrt(variance1)
x = np.linspace(-3,3.5,100, endpoint=True)
y1 = mlab.normpdf(x,mean1,sigma1)
fig, ax = plt.subplots()
ax.plot(x,y1)
mean2 = 0.4
variance2 = 2
sigma2 = math.sqrt(variance2)
y = np.linspace(-4,3.5,100, endpoint=False)
y2 = mlab.normpdf(y,mean2,sigma2)
ax.plot(x,y2)
ax.fill_between(x[:30], y1[:30], color='blue')
ax.fill_between(x[:30], y2[:30], color='green')
ax.fill_between(x[-30:], y1[-30:], y2[-30:], color='red', alpha=0.5)
ax.set_yticks([])
ax.set_xticks([])
plt.savefig('fill_norms.png')
plt.show()
This is a crazy simple example -- see the cookbook examples and look at the where clause; your fill-between highlights can adapt to changes in the lines you're plotting (e.g., an automatic red fill_between everywhere BADTHING exceeds GOODTHING, without your having to figure out the index (30 or -30 in this example)).

Python - Matplotlib: normalize axis when plotting a Probability Density Function

I'm using Python and some of its extensions to get and plot the Probability Density Function. While I manage to plot it, in its form, at least, I don't manage to succeed on scalating the axis.
import decimal
import numpy as np
import scipy.stats as stats
import pylab as pl
import matplotlib.pyplot as plt
from decimal import *
from scipy.stats import norm
lines=[]
fig, ax = plt.subplots(1, 1)
mean, var, skew, kurt = norm.stats(moments='mvsk')
#Here I delete some lines aimed to fill the list with values
Long = len(lines)
Maxim = max(lines) #MaxValue
Minim = min(lines) #MinValue
av = np.mean(lines) #Average
StDev = np.std(lines) #Standard Dev.
x = np.linspace(Minim, Maxim, Long)
ax.plot(x, norm.pdf(x, av, StDev),'r-', lw=3, alpha=0.9, label='norm pdf')
weights = np.ones_like(lines)/len(lines)
ax.hist(lines, weights = weights, normed=True, histtype='stepfilled', alpha=0.2)
ax.legend(loc='best', frameon=False)
plt.show()
The result is
While I would like to have it expressed
- In the x-axis centered in 0 and related to the standard deviation
- In the y-axis, related to the histogram and the %s (normalized to 1)
For the x-axis as the image below
And like this last image for the y-axis
I've managed to escalate the y-axis in a histogram by plotting it individually with the instruction weights = weights and setting it into the plot, but I can't do it here. I include it in the code but actually it does nothing in this case.
Any help would be appreciated
the y-axis is normed in a way, that the area under the curve is one.
And adding equal weights for every data point makes no sense if you normalize anyway with normed=True.
first you need to shift your data to 0:
lines -= mean(lines)
then plot it.
ythis should be a working minimal example:
import numpy as np
from numpy.random import normal
import matplotlib.pyplot as plt
from scipy.stats import norm
# gaussian distributed random numbers with mu =4 and sigma=2
x = normal(4, 2, 10000)
mean = np.mean(x)
sigma = np.std(x)
x -= mean
x_plot = np.linspace(min(x), max(x), 1000)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.hist(x, bins=50, normed=True, label="data")
ax.plot(x_plot, norm.pdf(x_plot, mean, sigma), 'r-', label="pdf")
ax.legend(loc='best')
x_ticks = np.arange(-4*sigma, 4.1*sigma, sigma)
x_labels = [r"${} \sigma$".format(i) for i in range(-4,5)]
ax.set_xticks(x_ticks)
ax.set_xticklabels(x_labels)
plt.show()
output image is this:
and you have too much imports.
you import decimals twice, one time even with *
and then numpy, pyplot and scipy are included in pylab. Also why import the whole scipy.stats and then again import just norm from it?

Categories