I have 4 variables like this:
# generate 4 random variables from the random, gamma, exponential, and uniform distributions
x1 = np.random.normal(-2.5, 1, 10000)
x2 = np.random.gamma(2, 1.5, 10000)
x3 = np.random.exponential(2, 10000)+7
x4 = np.random.uniform(14,20, 10000)
And I need to create one figure with 4 subplots.
so I tried this:
plt.figure(figsize=(9,3))
plt.subplot(1,4,1)
plt.hist(x1, normed=True, bins=20, alpha=0.5)
plt.subplot(1,4,2)
plt.hist(x2, normed=True, bins=20, alpha=0.5)
plt.subplot(1,4,3)
plt.hist(x3, normed=True, bins=20, alpha=0.5)
plt.subplot(1,4,4)
plt.hist(x4, normed=True, bins=20, alpha=0.5)
plt.axis([-7,21,0,0.6])
And I got this result
Now I want to create an animation on the subplots, so I did the following (trying one subplot only)
import matplotlib.animation as animation
def update(curr):
if curr == n:
a.event_source.stop()
plt.cla()
plt.figure(figsize=(9,3))
plt.subplot(1,4,1)
plt.hist(x1, normed=True, bins=20, alpha=0.5)
plt.axis([-7,21,0,0.6])
plt.gca().set_title('Sample')
plt.gca().set_ylabel('Frequency')
plt.gca().set_xlabel('Value')
plt.annotate('n = {}'.format(curr), [3.27])
fig = plt.figure()
a = animation.FuncAnimation(fig, update, interval=100)
However the end result is empty, nothing is shown.
Any idea?
I re-structured your code in order to plot the animation of the 4 subplots.
Without any specific indication on what you want to see changing between one frame and the next, I assume the number of sample drawn from each distribution is inscreasing in each frame by 10.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def update(curr):
N = 10*curr
x1 = np.random.normal(-2.5, 1, N)
x2 = np.random.gamma(2, 1.5, N)
x3 = np.random.exponential(2, N) + 7
x4 = np.random.uniform(14, 20, N)
ax[0].cla()
ax[0].hist(x1, bins = 20, alpha = 0.5, color = 'blue', edgecolor = 'blue')
ax[0].set_title('Normal')
ax[0].set_ylabel('Frequency')
ax[0].set_xlabel('Value')
ax[0].set_xlim(-6, 1)
ax[1].cla()
ax[1].hist(x2, bins = 20, alpha = 0.5, color = 'blue', edgecolor = 'blue')
ax[1].set_title('Gamma')
ax[1].set_ylabel('Frequency')
ax[1].set_xlabel('Value')
ax[1].set_xlim(0, 12)
ax[2].cla()
ax[2].hist(x3, bins = 20, alpha = 0.5, color = 'blue', edgecolor = 'blue')
ax[2].set_title('Exponential')
ax[2].set_ylabel('Frequency')
ax[2].set_xlabel('Value')
ax[2].set_xlim(7, 25)
ax[3].cla()
ax[3].hist(x4, bins = 20, alpha = 0.5, color = 'blue', edgecolor = 'blue')
ax[3].set_title('Uniform')
ax[3].set_ylabel('Frequency')
ax[3].set_xlabel('Value')
ax[3].set_xlim(14, 20)
ax[0].set_ylim(0, 250)
fig.suptitle(f'Number of samples: {N}')
plt.tight_layout()
fig, ax = plt.subplots(1, 4, figsize = (9, 3), sharey = 'all')
a = FuncAnimation(fig, update, interval = 100, frames = 81)
plt.show()
Related
I am creating a 2D matplotlib plot (i and j coordinates) which contains 10 subplots. Each subplot contains 150 by 150 grid cell data. How can I insert a small black-colored square mark (3 by 3 ) somewhere fixed (center at coordinates 62 and 62 ) on each generated heatmap sub-plot across those 10 sub-plots? The square mark would therefore contain 10 blocks from 60 to 64 in both x and y direction and contains a written text "Sale 1" centered at x 62 and y 62. My code below does not generate any patches. Any feedback is greatly appreciated.
from matplotlib.patches import Rectangle
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score, median_absolute_error
import os
import matplotlib.cm as cm
from mpl_toolkits import axes_grid1
import matplotlib.pyplot as plt
#import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.colors
import matplotlib.colors as colors
data = np.random.rand(10, 150, 150)
data = data.reshape(-1, 1)
property = "Sale"
pmin = data.min()
pmax = data.max()
v = np.linspace(round(pmin,3), round(pmax,3),15, endpoint=True)
v = [round(x,3) for x in v]
fig, ax = plt.subplots(2, 5, figsize=(160, 80))
row_count = 0
col_count = 0
for i in range(10):
sub_plot_data = data[(i)*(150*150):(i+1)*150*150]
x = 150
y = 150
#--------------------------- Define the map boundary ----------------------
xmin = 1258096.6
xmax = 1291155.0
ymin = 11251941.6
ymax = 11285000.0
pmin = min(sub_plot_data)
pmax = max(sub_plot_data)
# --------------------------- define color bar for Discrete color
bounds = np.linspace(-1, 1, 10)
Discrete_colors = plt.get_cmap('jet')(np.linspace(0,1,len(bounds)+1))
# create colormap without the outmost colors
cmap = mcolors.ListedColormap(Discrete_colors[1:-1]) #
actual_2d = np.reshape(sub_plot_data,(y,x))
im1 = ax[row_count, col_count].imshow(actual_2d, interpolation=None, cmap=cmap,
extent=(xmin, xmax, ymin, ymax), vmin=pmin, vmax=pmax)
plt.text(actual_2d[62, 62], actual_2d[62, 62], '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize= 90)
ax[row_count, col_count].set_title("Sale_Stores-%s - L: %s"%(i+1, layer),
fontsize=130, pad=44, x=0.5, y=0.999) # new
ax[row_count, col_count].set_aspect('auto')
ax[row_count, col_count].tick_params(left=False, labelleft=False, top=False,
labeltop=False, right=False, labelright=False, bottom=False, labelbottom=False) # new
#ax[row_count, col_count] = plt.gca()
plt.gca().add_patch(Rectangle((60, 60), 3, 3, edgecolor='black',
facecolor='black',fill=True,lw=2))
ax[row_count, col_count].add_patch(plt.text(62, 62, '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize= 90))
col_count +=1
if col_count == 5:
row_count +=1
col_count =0
fig.tight_layout(h_pad=10)
plt.subplots_adjust(left=0.02,
bottom=0.1,
right=0.91,
top=0.8,
wspace=0.1,
hspace=0.2)
cbaxes = fig.add_axes([0.94, 0.05, 0.02, 0.8])
cbar = fig.colorbar(im1, ax=ax.ravel().tolist(), ticks=v, extend='both', cax =cbaxes)
cbar.ax.tick_params(labelsize=70)
#cbar.set_ticks(v)
cbar.ax.set_yticklabels([i for i in v], fontsize=120)
output_dir = r"D/test"
plot_dir = os.path.join(output_dir, reservoir_property)
if not os.path.exists(plot_dir):
os.makedirs(plot_dir)
fig.savefig(r"%s/per_allmodel.png"%(plot_dir))
I tried your code and made a couple of modifications: first, the graph size was too huge and caused errors, so I made it smaller; second, I simplified the subplots: axes has a list of subplot objects, so I took them out with axes.flat; third The second is modifying the text as annotations. The graph size has been reduced and the font size and spacing have been adjusted, so please modify it yourself. Finally, tick_params is not set since the color bar ticks are disabled.
fig, axes = plt.subplots(2, 5, figsize=(16, 8))
row_count = 0
col_count = 0
for i,ax in enumerate(axes.flat):
sub_plot_data = data[(i)*(150*150):(i+1)*150*150]
x = 150
y = 150
#--------------------------- Define the map boundary ----------------------
xmin = 1258096.6
xmax = 1291155.0
ymin = 11251941.6
ymax = 11285000.0
pmin = min(sub_plot_data)
pmax = max(sub_plot_data)
# --------------------------- define color bar for Discrete color
bounds = np.linspace(-1, 1, 10)
Discrete_colors = plt.get_cmap('jet')(np.linspace(0,1,len(bounds)+1))
# create colormap without the outmost colors
cmap = mcolors.ListedColormap(Discrete_colors[1:-1]) #
actual_2d = np.reshape(sub_plot_data,(y,x))
#im = ax.imshow(actual_2d, interpolation=None, cmap=cmap, extent=(xmin, xmax, ymin, ymax), vmin=pmin, vmax=pmax)
im = ax.imshow(actual_2d, interpolation=None, cmap=cmap)
ax.text(actual_2d[62, 62], actual_2d[62, 62]-10, '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize=18)
ax.set_title("Sale_Stores-%s - L: %s"%(i+1, 1), fontsize=14, pad=30, x=0.5, y=0.999)
ax.set_aspect('auto')
ax.add_patch(Rectangle((60, 60), 6, 6, edgecolor='red', facecolor='red', fill=True, lw=2))
ax.text(62, 62, '%s' % 'Sale_1', ha='center', va='center', color='black', fontsize=14)
fig.tight_layout(h_pad=10)
plt.subplots_adjust(left=0.02,
bottom=0.1,
right=0.91,
top=0.8,
wspace=0.1,
hspace=0.5)
cbaxes = fig.add_axes([0.94, 0.05, 0.02, 0.8])
cbar = fig.colorbar(im, ax=axes.flat, ticks=v, extend='both', cax=cbaxes)
cbar.ax.tick_params(labelsize=10)
#cbar.set_ticks(v)
cbar.ax.set_yticklabels([str(i) for i in v], fontsize=12)
#plt.tick_params(left=False, labelleft=False, top=False, labeltop=False, right=False, labelright=False, bottom=False, labelbottom=False)
plt.show()
Im not sure if i use the wrong data or if there is and edit i need to do and not seeing it. It would be nice if someone could take a look at the code. The problem here is that yerr at the first bar is at x=0 and in the image the yerr is somewhere around 2.5
Does someone know what i did wrong or forgot to edit?
the end result should be:
my code:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
y_raw = np.random.randn(1000).cumsum() + 15
x_raw = np.linspace(0, 24, y_raw.size)
x_pos = x_raw.reshape(-1, 100).min(axis=1)
y_avg = y_raw.reshape(-1, 100).mean(axis=1)
y_err = y_raw.reshape(-1, 100).ptp(axis=1)
bar_width = x_pos[1] - x_pos[0]
x_pred = np.linspace(0, 30)
y_max_pred = y_avg[0] + y_err[0] + 2.3 * x_pred
y_min_pred = y_avg[0] - y_err[0] + 1.2 * x_pred
barcolor, linecolor, fillcolor = 'wheat', 'salmon', 'lightblue'
fig, axes = fig, ax = plt.subplots()
axes.set_title(label="Future Projection of Attitudes", fontsize=15)
plt.xlabel('Minutes since class began', fontsize=12)
plt.ylabel('Snarkiness (snark units)', fontsize=12)
fig.set_size_inches(8, 6, forward=True)
axes.fill_between(x_pred, y_min_pred, y_max_pred ,color='lightblue')
axes.plot(x_raw, y_raw, color='salmon')
vert_bars = axes.bar(x_pos, y_avg, yerr=y_err, color='wheat', width = bar_width, edgecolor='grey',error_kw=dict(lw=1, capsize=5, capthick=1, ecolor='gray'))
axes.set(xlim=[0, 30], ylim=[0,100])
plt.show()
yerr is meant to be the difference between the mean and the min/max. Now you're using the full difference between max and min. You might divide it by 2 to get a better approximation. To obtain the exact values, you could calculate them explicitly (see code example).
Further, by default, the bars are center aligned vs their x-position. You can use align='edge' to left-align them (as x_pos is calculated as the minimum of the range the bar represents). You could also set clip_on=False in the err_kw to make sure the error bars are never clipped by the axes.
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
y_raw = np.random.randn(1000).cumsum() + 15
x_raw = np.linspace(0, 24, y_raw.size)
x_pos = x_raw.reshape(-1, 100).min(axis=1)
y_avg = y_raw.reshape(-1, 100).mean(axis=1)
y_min = y_raw.reshape(-1, 100).min(axis=1)
y_max = y_raw.reshape(-1, 100).max(axis=1)
bar_width = x_pos[1] - x_pos[0]
x_pred = np.linspace(0, 30)
y_max_pred = y_avg[0] + y_err[0] + 2.3 * x_pred
y_min_pred = y_avg[0] - y_err[0] + 1.2 * x_pred
barcolor, linecolor, fillcolor = 'wheat', 'salmon', 'lightblue'
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_title(label="Future Projection of Attitudes", fontsize=15)
ax.set_xlabel('Minutes since class began', fontsize=12)
ax.set_ylabel('Snarkiness (snark units)', fontsize=12)
ax.fill_between(x_pred, y_min_pred, y_max_pred, color='lightblue')
ax.plot(x_raw, y_raw, color='salmon')
vert_bars = ax.bar(x_pos, y_avg, yerr=(y_avg - y_min, y_max - y_avg),
color='wheat', width=bar_width, edgecolor='grey', align='edge',
error_kw=dict(lw=1, capsize=5, capthick=1, ecolor='grey', clip_on=False))
ax.set(xlim=[0, 30], ylim=[0, 100])
plt.tight_layout()
plt.show()
I have been using Is it possible to get color gradients under curve in matplotlib? as a reference (you can see the similarities, however i cant for the life of me figure out how to push the shading all the way down to 0 on the Y AXIS, for some reason which i cant find out, it has an upward sloping straight line cutting off the shading, i cant find anything in my data to suggest why its doing this.
for context the y axis can show positive and negative and i want to fill the scale the whole way so using gradient colour to fill from 0 to the line (positive) then fill from 0 to the negative line (see my blue example from a previous chart -same data-)
Here is my code
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
# Variables
AUM = df['#AHD_AUM'].head(104)
MM = df['#AHD_Managed_Money_Net'].head(104)
PRICE = df['#AHD_Price'].head(104)
DATES = df['DATES'].head(104)
# Date Friendly Variables for Plot
List_AUM = df['#AHD_AUM'].head(104).to_list()
List_MM = df['#AHD_Managed_Money_Net'].head(104).to_list()
List_DATES = df['DATES'].head(104).to_list()
X = 0 * df['#AHD_AUM'].head(104)
# Make a date list changing dates with numbers to avoid the issue with the plot
interpreting dates
for i in range(len(df['DATES'].head(104))):
count = i
df['count'][i] = 120 - i
# X and Y data variables changed to arrays as when i had these set as dates
matplotlib hates it
x = df['count'].head(104).to_numpy()
y = df['#AHD_Managed_Money_Net'].head(104).to_numpy()
#DD = AUM.to_numpy()
#MMM = MM.to_numpy()
def main():
for _ in range(len(DD)):
gradient_fill(x,y)
plt.show()
def gradient_fill(x,y, fill_color=None, ax=None, **kwargs):
"""
"""
if ax is None:
ax = plt.gca()
line, = ax.plot(x, y, **kwargs)
if fill_color is None:
fill_color = line.get_color()
zorder = line.get_zorder()
alpha = line.get_alpha()
alpha = 1.0 if alpha is None else alpha
z = np.empty((100, 1, 4), dtype=float)
rgb = mcolors.colorConverter.to_rgb(fill_color)
z[:,:,:3] = rgb
z[:,:,-1] = np.linspace(0, alpha, 100)[:,None]
xmin, xmax, ymin, ymax = x.min(), x.max(), y.min(), y.max()
im = ax.imshow(z, aspect='auto', extent=[xmin, xmax, ymin, ymax],
origin='lower', zorder=zorder)
xy = np.column_stack([x, y])
# xy = np.vstack([[xmin, ymin], xy, [xmax, ymin], [xmin, ymin]]) ### i dont
need this so i have just commented it out
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
im.set_clip_path(clip_path)
ax.autoscale(True)
return line, im
main()
this is my current output
An easier way to clip the gradient by the curve, is to use a polygon obtained from fill_between.
Here is some example code to get you started.
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(123)
x = np.linspace(0, 10, 200)
y = np.random.normal(0.01, 1, 200).cumsum()
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(x, y)
ylim = ax.get_ylim()
grad1 = ax.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap='Blues', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), 0, y.max()], origin='lower')
poly_pos = ax.fill_between(x, y.min(), y, alpha=0.1)
grad1.set_clip_path(poly_pos.get_paths()[0], transform=ax.transData)
poly_pos.remove()
grad2 = ax.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap='Reds', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), y.min(), 0], origin='upper')
poly_neg = ax.fill_between(x, y, y.max(), alpha=0.1)
grad2.set_clip_path(poly_neg.get_paths()[0], transform=ax.transData)
poly_neg.remove()
ax.set_ylim(ylim)
ax.axhline(0, color='black') # show a line at x=0
plt.show()
PS: vmin in imshow can be used to remove the color range where it's very light:
grad1 = ax.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap='Blues', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), 0, y.max()], origin='lower')
grad2 = ax.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap='Reds', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), y.min(), 0], origin='upper')
import pandas as pd # For data handling
import seaborn as sns # For plotting
import numpy as np
import matplotlib.pyplot as plt # For plotting
import matplotlib
#some preferred user settings
plt.rcParams['figure.figsize'] = (18.0, 12.0)
pd.set_option('display.max_columns', None)
%matplotlib inline
import warnings
warnings.filterwarnings(action='ignore')
from mpl_toolkits.axisartist.parasite_axes import HostAxes, ParasiteAxes
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
import datetime as dt
import matplotlib.dates as mdates
import pandas
Metal = CAD
# Variables
AUM = Metal.iloc[:,[7]].head(104)
MM = Metal.iloc[:,[0]].head(104)
PRICE = Metal.iloc[:,[8]].head(104)
#Last_Report = Metal.iloc[:,[9]].head(1).dt.strftime('%d %b %Y').to_list()
DATES = Metal.iloc[:,[10]].head(104)
# Dataframe for Net Position High
Net_High = Metal[Metal.iloc[:,[0]] == Metal.iloc[:,[0]].max()]
# Variables for Chart Annotation for Net Position High
Pos_High_Date = Net_High.iloc[:, [0]]
Pos_High_AUM = Net_High.iloc[:, [7]][0]/[1000000000]
Pos_High_Price = Net_High.iloc[:, [8]].to_numpy()[0].round().astype('int')
Pos_High = Net_High.iloc[:, [0]][0].astype('int')
Str_Date = mdates.num2date(Pos_High_Date)
Str_Date = pd.to_datetime(Str_Date[0]).strftime("%d %b %y")[0]
# Dataframe for Net Position Low
Net_Low = df[df['#CAD_Managed_Money_Net'] == df['#CAD_Managed_Money_Net'].head(104).min()]
# Variables for Chart Annotation for Net Position High
Pos_Low_Date = Net_Low.iloc[:, [55]].to_numpy()
Pos_Low_AUM = Net_Low.iloc[:, [26]].to_numpy()[0].round()/[1000000000]
Pos_Low_Price = Net_Low.iloc[:, [27]].to_numpy()[0].round().astype('int')
Pos_Low = Net_Low['#CAD_Managed_Money_Net'][0].astype('int')
Str_Date_Low = mdates.num2date(Pos_Low_Date)
Str_Date_Low = pd.to_datetime(Str_Date_Low[0]).strftime("%d %b %y")[0]
# C Brand Colour Scheme
C = ['deepskyblue', '#003399', 'slategray', '#027608','#cc0000']
def make_patch_spines_invisible(ax):
ax.set_frame_on(True)
ax.patch.set_visible(False)
for sp in ax.spines.values():
sp.set_visible(False)
fig, host = plt.subplots(figsize=(25,15))
fig.subplots_adjust(right=0.8)
#twinx() creates another axes sharing the x axis we do this twice
par1 = host.twinx()
par2 = host.twinx()
# Offset the right spine of par2 the ticks
par2.spines["right"].set_position(("axes",1.08))
#because par2 was created by twinx the frame is off so we need to use the method created above
make_patch_spines_invisible(par2)
# second, show the right spine
par2.spines["right"].set_visible(True)
######### Colouring in Plots
x = DATES
y = MM
ylim = host.get_ylim()
Long = host.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap= 'Blues', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), 0, y.max()], origin='lower')
poly_pos = host.fill_between(x, y.min(), y, alpha=0.1)
Long.set_clip_path(poly_pos.get_paths()[0], transform=host.transData)
poly_pos.remove()
Short = host.imshow(np.linspace(0, 1, 256).reshape(-1, 1), cmap='OrRd', vmin=-0.5, aspect='auto',
extent=[x.min(), x.max(), y.min(), 0], origin='upper')
poly_neg = host.fill_between(x, y, y.max(), alpha=0.1)
Short.set_clip_path(poly_neg.get_paths()[0], transform=host.transData)
poly_neg.remove()
##########
#plot data
p1, = host.plot(DATES, MM, label="Managed Money Net Position", linewidth=0.0,color = Citi[1], alpha = 0.8)
p2, = par1.plot(DATES, AUM, label="AUM",linewidth=1, marker = '$A$',mew = 1,mfc = 'w', color = Citi[0], alpha = 0.8)
p3, = par2.plot(DATES, PRICE, label="3M Price",linewidth=1, marker = '$p$', color = Citi[2], alpha = 0.8)
#Automatically scale and format
host_labels = ['{:,.0f}'.format(x) + 'K Lots' for x in host.get_yticks()/1000]
host.set_yticklabels(host_labels)
par1_labels = ['{:,.1f}'.format(x) + ' $Billion' for x in par1.get_yticks()/1000000000]
par1.set_yticklabels(par1_labels)
par2_labels = ['{:,.0f}'.format(x) + ' $' for x in par2.get_yticks()]
par2.set_yticklabels(par2_labels)
# x Axis formatting (date)
formatter = matplotlib.dates.DateFormatter('%b- %Y')
host.xaxis.set_major_formatter(formatter)
# Rotates and right-aligns the x labels so they don't crowd each other.
for label in host.get_xticklabels(which='major'):
label.set(rotation=30, horizontalalignment='right')
# Axis Labels
host.set_xlabel("Date")
host.set_ylabel("Managed Money Net Position")
par1.set_ylabel("AUM")
par2.set_ylabel("3M Price")
# Tick Parameters
tkw = dict(size=10, width=2.5)
# Set tick colours
host.tick_params(axis = 'y', colors = Citi[1], **tkw)
par1.tick_params(axis = 'y', colors = Citi[0], **tkw)
par2.tick_params(axis = 'y', colors = Citi[2], **tkw)
#host.tick_params(which='major',axis = 'x',direction='out', colors = Citi[2], **tkw)
#plt.xticks(x, rotation='vertical')
#host.xaxis.set_major_locator(AutoMajorLocator())
host.xaxis.set_major_locator(MultipleLocator(24))
host.tick_params('x',which='major', length=7)
#Label colours taken from plot
host.yaxis.label.set_color(p1.get_color())
par1.yaxis.label.set_color(p2.get_color())
par2.yaxis.label.set_color(p3.get_color())
# Map Title
host.set_title('Aluminium Managed Money Net Positioning as of %s'% Last_Report[0],fontsize='large')
#Colour Spines cant figure out how to do it for the host
par1.spines["right"].set_edgecolor(p2.get_color())
par2.spines["right"].set_edgecolor(p3.get_color())
###### Annotation Tests ##########
## Net Position High Box
host.annotate(f' Net Position High | {Pos_High} \n Date | {Str_Date} \n AUM | ${Pos_High_AUM[0].round(1)} Billion\n 3M Price | ${Pos_High_Price[0]}$',
xy=(Pos_High_Date, Pos_High), xycoords='data',
xytext=(0.02, .85), textcoords='axes fraction',
horizontalalignment='left',
verticalalignment='bottom',
color='white',
bbox=dict(boxstyle="round", fc= Citi[1],edgecolor='white'),
arrowprops=dict(
facecolor='black',
arrowstyle= '->'))
## Net Position Low Box
host.annotate(f' Net Position Low | {Pos_Low} \n Date | {Str_Date_Low} \n AUM | ${Pos_Low_AUM[0].round(1)} Billion\n 3M Price | ${Pos_Low_Price[0]}$',
xy=(Pos_Low_Date, Pos_Low), xycoords='data',
xytext=(0.02, .80), textcoords='axes fraction',
horizontalalignment='left',
verticalalignment='top',
color='white',
bbox=dict(boxstyle="round", fc= Citi[4],edgecolor='white'),
arrowprops=dict(
facecolor='black',
arrowstyle= '->'))
################
# Legend - a little complicated as we have to take from multiple axis
lines = [p1, p2, p3]
########## Plot text and line on chart if you want to
# host.axvline(x = DATES[52] , linestyle='dotted', color='black') ###Dotted Line when Needed
# host.text(2020.3, 10, 'Managed Money \n Aluminium')
# host.text(2020.5, 92, r'Ali',color='black')
# host.text(2020.8,15, r'some event', rotation=90)
host.legend(lines,[l.get_label() for l in lines],loc=2, fontsize=12,frameon=False)
plt.savefig('multiple_axes.png', dpi=300, bbox_inches='tight')
I need to show a confidence interval, like in this image:
but I don't know how to do it. I've tried doing lb.fill_between(x, (y1-ci), (y1+ci), color = 'b', alpha = 0.1) but it returns the error: AttributeError: 'list' object has no attribute 'fill_between'.
This is my code:
import matplotlib.pyplot as plt
x = [10, 100, 1000]
y1 = [215103, 22824279.7, 22063128311]
y2 = [211298.5, 21315505.2, 20563930722]
plt.subplot(2, 2, 1)
ci = 1300
#la = plt.plot(x,y,'b*', label = 'normal')
lb = plt.plot(x,y1, '#FA8072', label = 'LI')
lc = plt.plot(x,y2, '#7FFFD4', label = 'LU')
plt.legend(loc = 'upper left')
plt.title("L1-dcache-loads")
plt.xscale("log")
Thanks in advance!
Use fill_between like this:
plt.figure()
plt.fill_between(x, y1, y2, edgecolor='g', facecolor='g', alpha=0.3)
y1 is your lower bound curve, and y2 is your upper bound curve. Output:
In your example:
plt.figure()
plt.plot(x,y1, '#FA8072', label = 'LI')
plt.fill_between(x, np.array(y1)-ci, np.array(y1)+ci, edgecolor='r', facecolor='r', alpha=0.3)
plt.plot(x,y2, '#7FFFD4', label = 'LU')
plt.fill_between(x, np.array(y2)-ci, np.array(y2)+ci, edgecolor='g', facecolor='g', alpha=0.3)
plt.legend(loc = 'upper left')
plt.title("L1-dcache-loads")
plt.xscale("log")
But the intervals are too small to see.
I need to make some plots with multiple parameters, and I choosed to make it more interactive with matplotlib sliders. For some practise before my actual task I tried to make it relativelly simple, but my sliders does not work. Here is the code, which is inspired from here.
Code:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.widgets as mw
from scipy import stats
mu = 1
sigma = 3
a = 2
b = 3
axis_color = 'lightgoldenrodyellow'
x = [i for i in range(-100,100,1)]
normal_pdf = stats.norm.pdf(x, mu, sigma)
a_normal_pdf = [i*a for i in normal_pdf]
ab_normal_pdf = [i*b*a for i in normal_pdf]
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax4.axis('off')
#sliders
a_slider_ax = fig.add_axes([0.6, 0.25, 0.25, 0.03], axisbg=axis_color)
a_slider = mw.Slider(a_slider_ax, 'a', 1, 100, valinit = a)
b_slider_ax = fig.add_axes([0.6, 0.4, 0.25, .03], axisbg = axis_color)
b_slider = mw.Slider(b_slider_ax, 'b', 1, 100, valinit = b)
#function for sliders
def sliders_on_change(val):
a_normal_pdf.set_ydata([x*a_slider for x in normal_pdf])
ab_normal_pdf.set_ydata([x*a_slider*b_slider for x in normal_pdf])
fig.canvas.draw_idle()
a_slider.on_changed(sliders_on_change)
b_slider.on_changed(sliders_on_change)
ax1.plot(x, normal_pdf, 'r-')
ax2.plot(x, a_normal_pdf, 'bo')
ax3.plot(x, ab_normal_pdf, 'g*')
plt.show()
I do not fully understand HOW sliders should work, so its maybe the problem instead of idle issue as here, because I tried it in spyder and in jupyter as well, no difference. I can move with sliders, but I cant change the a_normal_pdf nor ab_normal_pdf.
You have two issues in your code:
using the slider object a_slider in place of the slider's current value a_slider.val
the method set_ydata changes the y-data of a Line2D plot object (I saved it in a variable p1 to be able to modify it)
Modified code (hope this helps)
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.widgets as mw
from scipy import stats
mu = 1
sigma = 3
a = 2
b = 3
axis_color = 'lightgoldenrodyellow'
x = [i for i in range(-100,100,1)]
normal_pdf = stats.norm.pdf(x, mu, sigma)
a_normal_pdf = [i*a for i in normal_pdf]
ab_normal_pdf = [i*b*a for i in normal_pdf]
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax4.axis('off')
#sliders
a_slider_ax = fig.add_axes([0.6, 0.25, 0.25, 0.03], axisbg=axis_color)
a_slider = mw.Slider(a_slider_ax, 'a', 1, 100, valinit = a)
b_slider_ax = fig.add_axes([0.6, 0.4, 0.25, .03], axisbg = axis_color)
b_slider = mw.Slider(b_slider_ax, 'b', 1, 100, valinit = b)
#function for sliders
def sliders_on_change(val):
p1.set_ydata([x*a_slider.val for x in normal_pdf])
p2.set_ydata([x*a_slider.val*b_slider.val for x in normal_pdf])
fig.canvas.draw_idle()
a_slider.on_changed(sliders_on_change)
b_slider.on_changed(sliders_on_change)
p1,=ax1.plot(x, normal_pdf, 'r-')
p2,=ax2.plot(x, a_normal_pdf, 'bo')
p3,=ax3.plot(x, ab_normal_pdf, 'g*')
plt.show()