I want to reproduce this plot. The errors are shown in the bottom of the plot. Can you please share how its done?
There is an example that I found here on stackoverflow, but it is in R.
How to create a graph showing the predictive model, data and residuals in R
You can create such plot in Matplotlib only by using add_axes. Here is an example.
from scipy.optimize import curve_fit
#Data
x = arange(1,10,0.2)
ynoise = x*numpy.random.rand(len(x))
#Noise; noise is scaled by x, in order to it be noticable on a x-squared function
ydata = x**2 + ynoise #Noisy data
#Model
Fofx = lambda x,a,b,c: a*x**2+b*x+c
#Best fit parameters
p, cov = curve_fit(Fofx,x,ydata)
#PLOT
fig1 = figure(1)
#Plot Data-model
frame1=fig1.add_axes((.1,.3,.8,.6))
#xstart, ystart, xend, yend [units are fraction of the image frame, from bottom left corner]
plot(x,ydata,'.b') #Noisy data
plot(x,Fofx(x,*p),'-r') #Best fit model
frame1.set_xticklabels([]) #Remove x-tic labels for the first frame
grid()
#Residual plot
difference = Fofx(x,*p) - ydata
frame2=fig1.add_axes((.1,.1,.8,.2))
plot(x,difference,'or')
grid()
This is an old post, but seeing that this is a top hit for making bottom residual plots, I thought it is useful to modify the code by #jaydeepsb that runs as is.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Data
x = np.arange(1,10,0.2)
ynoise = x*np.random.rand(len(x))
ydata = x**2 + ynoise
Fofx = lambda x,a,b,c: a*x**2+b*x+c
p, cov = curve_fit(Fofx,x,ydata)
# Upper plot
fig1 = plt.figure(1)
frame1 = fig1.add_axes((.1,.3,.8,.6))
plt.plot(x,ydata,'.b')
plt.plot(x,Fofx(x,*p),'-r')
frame1.set_xticklabels([])
plt.grid()
# Residual plot
difference = Fofx(x,*p) - ydata
frame2 = fig1.add_axes((.1,.1,.8,.2))
plt.plot(x,difference,'or')
plt.grid()
I think you are looking for errorbars like this pylab_examples example code: errorbar_demo.py
You can add an additional subplot and plot the points with the error bars.
Edit: No border between plots:
from pylab import *
subplots_adjust(hspace=0.,wspace=0.)
subplot(211)
imshow(rand(100,100), cmap=cm.BuPu_r)
subplot(212)
imshow(rand(100,100), cmap=cm.BuPu_r)
show()
Related
I have been trying to plot a smooth graph, and here is my code
import matplotlib.pyplot as plt
#fig,axes= plt.subplots(nrows=6, ncols=1, squeeze=False)
x = df["DOY"]
y = df["By"]
z = df["Bz"]
a = df["Vsw"]
b = df["Nsw"]
c = df["magnetopause_distance"]
d = df["reconnection_rate"]
And after that, I used the following logic to plot the same
#create a figure
fig=plt.figure()
#define subplots and define their position
plt1=fig.add_subplot(611)
plt2=fig.add_subplot(612)
plt3=fig.add_subplot(613)
plt4=fig.add_subplot(614)
plt5=fig.add_subplot(615)
plt6=fig.add_subplot(616)
plt1.plot(x,y,'black',linewidth=0.5,marker=None)
plt1.set_ylabel("By")
plt1.set_title("3-6 July 2003")
plt2.plot(x,z,'black',linewidth=0.5)
plt2.set_ylabel("Bz")
plt3.plot(x,a,'black',linewidth=0.5)
plt3.set_ylabel("Vsw")
plt4.plot(x,b,'black',linewidth=0.5)
plt4.set_ylabel("Nsw")
plt5.plot(x,c,'black',linewidth=0.5)
plt5.set_ylabel("MD")
plt6.plot(x,d,'black',linewidth=0.5)
plt6.set_ylabel("MRR")
plt.subplots_adjust(hspace = 2,wspace = 2)
#saving plot in .jpg format
plt.savefig('myplot01.jpg', format='jpeg',dpi=500, bbox_inches='tight')
Finally, I am getting a plot like this:
What I want is something like this:
Sorry for the typos. Thanks for your time :)
Use:
from scipy.interpolate import UnivariateSpline
import numpy as np
list_x_new = np.linspace(min(x), max(x), 1000)
list_y_smooth = UnivariateSpline(x, y, list_x_new)
plt.plot(list_x_new, list_y_smooth)
plt.show()
This is for one of the graphs, you can substitute the values in list_y_smooth in place of y according to the values you want to plot.
I'm trying to plot bar hist of interest rates and attach to it a PDF line. I have looked for solutions and found a way with kdeplot.
The result is pretty strange the kdeplot line is much higher than the bars hist and I don't know how to fix it.
After applying kdeplot:
Before applying kdeplot:
Here is the code that I'm using:
df=pd.read_excel('interestrate.xlsx')
k=0.0005
bin_steps = np.arange(start = df['Interest rate Real'].min(), stop = df['Interest rate Real'].max(), step = k)
ax = df['Interest rate Real'].hist(bins = bin_steps, figsize=[10,5])
ax1 = df['Interest rate Real']
vals = ax.get_xticks()
ax.set_xticklabels(['{:,.2%}'.format(x) for x in vals])
ax.set_yticklabels(['{:,.2%}'.format(x) for x in vals])
ax.set_title("PDF for Real Interest Rate")
#sns.kdeplot(ax1)
The following code snippet should set you in the right direction (just insert your data):
import scipy.stats as st
y = np.random.randn(1000) # your data goes here
plt.hist(y,50, density=True)
mn, mx = plt.xlim()
plt.xlim(mn, mx)
x = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(y)
plt.plot(x, kde.pdf(x));
Alternatively with seaborn:
import seaborn as sns
plt.hist(y,50, density=True)
sns.kdeplot(y);
or as simple as:
sns.distplot(y)
I am plotting a map with arrows on top of it. These arrows represent winddirections, average windspeed (per direction) and the occurence (per direction).
The direction is indicated by the direction of the arrow. The length of the arrow indicated the average windspeed in that direction. The color of the arrow indicates the occurence of winds in such a direction.
This all works fine with the script below:
windData = pd.read_csv(src+'.txt'), sep='\t', names=['lat', 'lon', 'wind_dir_start', 'wind_dir_end', 'total_num_data_points','num_data_points', 'avg_windspeed']).dropna()
# plot map
m = Basemap(llcrnrlon=minLon, llcrnrlat=minLat, urcrnrlon=maxLon, urcrnrlat=maxLat, resolution='i')
Left, Bottom = m(minLon, minLat)
Right, Top = m(maxLon, maxLat)
# get x y
x, y = m(windData['lon'], windData['lat'])
# angles
angleStart = -windData['wind_start']+90
angleStart[angleStart<0] = np.radians(angleStart[angleStart<0]+360.)
angleEnd = -windData['wind_end']+90
angleEnd[angleEnd<0] = np.radians(angleEnd[angleEnd<0]+360.)
angle = angleStart + math.radians(binSize/2.)
xux = np.cos(angle) * windData['avg_windspeed']
yuy = np.sin(angle) * windData['avg_windspeed']
# occurence
occurence = (windData['num_data_points']/windData['total_num_data_points'])
xi = np.linspace(minLon, maxLon, 300)
yi = np.linspace(minLat, maxLat, 300)
# plotting
## xux and yuy are used negatively because they are measured as "coming from" and displayed as "going to"
# To make things more readable I left a threshold for the occurence out
# I usually plot x, y, xux, yuy and the colors as var[occurence>threshold]
Q = m.quiver(x, y, -xux, -yuy, scale=75, zorder=6, color=cm.jet, width=0.0003*Width, cmap=cm.jet)
qk = plt.quiverkey(Q, 0.5, 0.92, 3, r'$3 \frac{m}{s}$', labelpos='S', fontproperties={'weight': 'bold'})
m.scatter(x, y, c='k', s=20*np.ones(len(x)), zorder=10, vmin=4.5, vmax=39.)
This plot shows the arrows well, but now I want to add a colormap that indicates the percentage of occurence next to the plot. How would I do this?
OK
Usual imports, plus import matplotlib
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
Fake the data to be plotted (tx for the MCVE)
NP = 10
np.random.seed(1)
x = np.random.random(NP)
y = np.random.random(NP)
angle = 1.07+np.random.random(NP) # NE to NW
velocity = 1.50+np.random.random(NP)
o = np.random.random(NP)
occurrence = o/np.sum(o)
dx = np.cos(angle)*velocity
dy = np.sin(angle)*velocity
Create a mappable so that Matplotib has no reason to complain "RuntimeError: No mappable was found to use for colorbar creation."
norm = matplotlib.colors.Normalize()
norm.autoscale(occurrence)
cm = matplotlib.cm.copper
sm = matplotlib.cm.ScalarMappable(cmap=cm, norm=norm)
sm.set_array([])
and plot the data
plt.quiver(x, y, dx, dy, color=cm(norm(o)))
plt.colorbar(sm)
plt.show()
References:
A logarithmic colorbar in matplotlib scatter plot
,
Drawing a colorbar aside a line plot, using Matplotlib
and
Different colours for arrows in quiver plot.
P.S. In recent (for sure in 3.+) Matplotlib releases the cm.set_array incantation is no more necessary
Do you want the colorbar to show the different wind speeds? If so, it might be sufficient to place plt.colorbar() between the lines Q = m.quiver(...) and qk = ....
I want to do a quiver plot on a polar basemap plot. I have a regular lat/lon grid, and because there are more grid boxes at the higher latitudes, my code plots as many quivers at the pole as on the equator, so they overlap etc. How can I make the density of quivers latitude-dependent?
This is the code I use
import numpy as np
from mpl_toolkits.basemap import Basemap, addcyclic
import matplotlib.pyplot as plt
m_mu = Basemap(projection='npstere',boundinglat=10,lon_0=0,resolution='l',round=True)
lats=np.arange(0.,91.,15.)
lons=np.arange(-180.,181.,30.)
valin_u=np.array([[np.random.randn() for y in range(len(lons))] for x in range(len(lats))])
valin_v=np.array([[np.random.randn() for y in range(len(lons))] for x in range(len(lats))])
del x,y
valin = np.sqrt( valin_u**2 + valin_v**2 )
mu_cyclic, lons_cyclic = addcyclic(valin, lons)
mu_cyclic_u, lons_cyclic = addcyclic(valin_u, lons)
mu_cyclic_v, lons_cyclic = addcyclic(valin_v, lons)
grid = np.meshgrid( lons_cyclic, lats )
x, y = m_mu( *grid)
plt.figure()
cs = m_mu.pcolormesh(x, y, mu_cyclic)
csquiv = m_mu.quiver(x[::1,::1], y[::1,::1], mu_cyclic_u[::1,::1], mu_cyclic_v[::1,::1])
plt.show()
I guess I could write a function to set a latitude-dependent number of the values to .nan, but hopefully there is a better solution?
Many thanks for your help :-)
Sabine
Hi I want to add error bars to the histogram within this code.I have seen few post about it but I didn't find them helpful.this code produce random numbers with Gaussian distribution and a kernel estimation apply to it.I need to have errorbars to estimate how much the histogram is inaccurate with changing the bandwidth
from random import *
import numpy as np
from matplotlib.pyplot import*
from matplotlib import*
import scipy.stats as stats
def hist_with_kde(data, bandwidth = 0.3):
#set number of bins using Freedman and Diaconis
q1 = np.percentile(data,25)
q3 = np.percentile(data,75)
n = len(data)**(.1/.3)
rng = max(data) - min(data)
iqr = 2*(q3-q1)
bins =int((n*rng)/iqr)
print(bins)
x = np.linspace(min(data),max(data),200)
kde = stats.gaussian_kde(data,'scott')
kde._compute_covariance()
kde.set_bandwidth()
plot(x,kde(x),'r') # distribution function
hist(data,bins=bins,normed=True) # histogram
data = np.random.normal(0,1,1000)
hist_with_kde(data,30)
show()
Combining the answer mentioned above with your code:
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
def hist_with_kde(data, bandwidth = 0.3):
#set number of bins using Freedman and Diaconis
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
n = len(data)**(.1/.3)
rng = max(data) - min(data)
iqr = 2*(q3-q1)
bins =int((n*rng)/iqr)
print(bins)
x = np.linspace(min(data), max(data), 200)
kde = stats.gaussian_kde(data, 'scott')
kde._compute_covariance()
kde.set_bandwidth()
plt.plot(x, kde(x), 'r') # distribution function
y, binEdges = np.histogram(data, bins=bins, normed=True)
bincenters = 0.5*(binEdges[1:]+binEdges[:-1])
menStd = np.sqrt(y)
width = 0.2
plt.bar(bincenters, y, width=width, color='r', yerr=menStd)
data = np.random.normal(0, 1, 1000)
hist_with_kde(data, 30)
plt.show()
And have a look at the imports, as mentioned by MaxNoe
You can do it like this:
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
data = np.random.normal(size=10000)
# plt.hist gives you the entries, edges
# and drawables we do not need the drawables:
entries, edges, _ = plt.hist(data, bins=25, range=[-5, 5])
# calculate bin centers
bin_centers = 0.5 * (edges[:-1] + edges[1:])
# draw errobars, use the sqrt error. You can use what you want there
# poissonian 1 sigma intervals would make more sense
plt.errorbar(bin_centers, entries, yerr=np.sqrt(entries), fmt='r.')
plt.show()
Result:
This looks like a duplicate: Matplotlib histogram with errorbars
i.e. you have to use matplotlib.bar() to get error bars
Which in your example will look something like this:
You can replace
hist(data,bins=bins,normed=True)
with
y, binEdges = np.histogram(data,bins=bins)
bincenters = 0.5*(binEdges[1:]+binEdges[:-1])
menStd = np.sqrt(y)
width=0.1
bar(bincenters,y,width=width, color='r', yerr=menStd)
Play around with the parameters until you find something you like :)