After using "fill_between" (matplotlib) to draw a shaded line around a line, the shaded line is moved on the y-axis - matplotlib

it's my first question on this forum and I hope it won't be a very silly one haha.
I'm preparing a plot where I've drawn two lines and now I want to add a shaded line around them to show their variability. The problem is that when I plot it the shaded lines appear shifted on the y-axis and I don't know how to solve it, any idea?
This is my code and the result plot
enter image description here:
d_bas_q1 = df1["d_bas"] + df1['d_bas_q1']
d_bas_q3 = df1["d_bas"] + df1['d_bas_q3']
n_bas_q1 = df1["n_bas"] + df1['n_bas_q1']
n_bas_q3 = df1["n_bas"] + df1['n_bas_q3']
plt.figure(figsize=((10,8)))
plt.plot(df1['band'], df1["p_bas_cond"], color='k', alpha=0.1, linewidth=2)
plt.plot(df1['band'], df1["d_bas"], color='wheat',alpha=1, linewidth=2, label='m')
plt.fill_between(range(len(df1["d_bas"])), d_bas_q1, d_bas_q3, alpha=0.4, facecolor = 'wheat') # <---- i think the problem must be here
plt.plot(df1['band'], df1["n_bas"], color='cornflowerblue', alpha=0.7, linewidth=2, label='w')
plt.fill_between(range(len(df1["n_bas"])), n_bas_q1, n_bas_q3, alpha=0.4, facecolor = 'cornflowerblue') # <---- i think the problem must be here
plt.legend(loc="upper right")
plt.yscale('log')
plt.xlim([0, 10])
plt.ylim([plot_ymin1, plot_ymax1])
plt.xticks(range(0, 11, 1))
plt.minorticks_off()
plt.xlabel("x")
plt.ylabel('y')
plt.show()

Related

Integration of a piecewise regression in a subplot

I have the following code of a piecewise_regression:
data = data_heatmap_2017.copy()
data = data[['tre200h0_2017','Leistung:']].dropna()
xx = data['tre200h0_2017'].values.tolist()
yy = data['Leistung:'].values.tolist()
pw_fit = piecewise_regression.Fit(xx, yy, n_breakpoints=1)
pw_fit.summary()
If I do a single plot with the code below, I get a diagram piecewise_regression:
# Plot the data, fit, breakpoints and confidence intervals
pw_fit.plot_data(s=0.1)
# Pass in standard matplotlib keywords to control any of the plots
pw_fit.plot_fit(color="red", linewidth=2)
pw_fit.plot_breakpoints()
pw_fit.plot_breakpoint_confidence_intervals()
plt.xlabel("Lufttemperatur [°C]")
plt.ylabel("Leistung [kW]")
plt.show()
plt.close()
Now I would like to integrate the diagram piecewise regression within this subplots on position ax10:
fig, axs = plt.subplots(2, 5, figsize=(60,50), dpi=(100))
ax10 = axs[1,0]
ax10.set_title('2017, Signatur, Zähler: ' + Zaehler)
ax10.pw_fit.plot_data(s=0.1)
ax10.pw_fit.plot_fit(color="red", linewidth=2)
ax10.set_xlabel('Lufttemperatur [°C]')
ax10.set_ylabel('Leistung [kW]')
ax10.axis([-15, 35, min_Power, max_Power])
plt.show()
plt.close()
unfortunately the lines
ax10.pw_fit.plot_data(s=0.1)
ax10.pw_fit.plot_fit(color="red", linewidth=2)
do not work with the prefix ax10. I get an AttributeError 'AxesSubplot' object has no attribute 'pw_fit'. Any idea how to solve this? Thank you!

Matplotlib subplots size bigger than figure size

I discovered Matplotlib and I have a rendering problem. The 5 subplot I create step on each other, the xaxis labels and titles are behind the other plot.
Here is a part of the code I use :
fig, axs = plt.subplots(5,figsize=(8,25))
axs[0].plot(array_system_index, array_system_value, label="System", color="red", linewidth=1)
axs[0].set(xlabel="time", ylabel="Latency (µs)", yscale="log", title="System")
axs[0].axis([0, len(array_system_value), 1, 10000])
axs[1].plot(array_core0_index, array_core0_value, label="core 0", color="green", linewidth=1)
axs[1].set(xlabel="Time", ylabel="Latency (µs)", yscale="log", title="Core1")
axs[1].axis([0, len(array_core0_value), 1, 10000])
...
fig.tight_layout()
plt.show()
# fig.set_size_inches((15, 8), forward=False) # Break the png file
fig.savefig("my_graph.png", dpi=500)
Here is the result :
Graph
Do you know how can I increase the size of the figure itself ?
I tried to it after the subplot but it doesn't work and break the saved .png.

how to remove the white space of invisiable axes in matplotlib during active plot?

I want to completely remove white space around my axes during active plot (not save_fig as others asked).
Here we cannot use bbox_inches='tight'. I can use tight_layout(pad=0).
When axis is on, it works fine, it shows all the ticks and x-y labels.
However, in some cases, I set the axis off. What I expected is to see the contents expand to fill up the empty space where the axes are. However, this does not work. It still keep the padding as there are still x-y labels and axes.
How can I remove the white space of invisible axes objects?
edit:
I am aware that I can use ax.set_yticks([]) and ax.set_xticks([]) to turn those off. But this is clumsy, I have to remember the the ticks before I clear them. And if I remove-then-add those ticks. The ticks cannot automatically update any more.
I wonder is there any more straightforward way to do this?
We can still see there is a small border spacing even after removing all ticks. If someone can come up a way to remove that too. It will be fantastic.
I would also like to keep the title if there is one. Thus the hard-coded ax.set_position([0,0,1,x]) is not very good for this usage. Surely we can still try to get the top spacing when there is a title, but if someone can provide a more direct/simple way to handle this, it will be preferred.
Example code:
def demo_tight_layout(w=10, h=6, axisoff=False, removeticks=False):
fig,ax = plt.subplots()
fig.set_facecolor((0.8, 0.8, 0.8))
rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
ax.add_patch(rect)
ax.plot([-w/2,w/2], [-h/2,h/2])
ax.plot([-w/2,w/2], [h/2,-h/2])
ax.set_ylabel("ylabel")
ax.margins(0)
_texts = []
if axisoff:
ax.set_axis_off()
_texts.append("axisoff")
if removeticks:
ax.set_xticks([])
ax.set_yticks([])
ax.set_ylabel("")
_texts.append("removeticks")
fig.text(0.5, 0.6, " ".join(_texts))
fig.tight_layout(pad=0)
plt.show()
return fig, ax, text
You may adjust the subplot parameters depending on whether you turned the axis off or not.
import matplotlib.pyplot as plt
from matplotlib import patches
def demo_tight_layout(w=10, h=6, axisoff=False):
fig,ax = plt.subplots()
fig.set_facecolor((0.8, 0.8, 0.8))
rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
ax.add_patch(rect)
ax.plot([-w/2,w/2], [-h/2,h/2])
ax.plot([-w/2,w/2], [h/2,-h/2])
ax.set_ylabel("ylabel")
ax.margins(0)
_texts = []
fig.tight_layout()
if axisoff:
ax.set_axis_off()
_texts.append("axisoff")
params = dict(bottom=0, left=0, right=1)
if ax.get_title() == "":
params.update(top=1)
fig.subplots_adjust(**params)
fig.text(0.5, 0.6, " ".join(_texts))
plt.show()
Now demo_tight_layout(axisoff=True) produces
and demo_tight_layout(axisoff=False) produces
You need to set the axes position to fill the figure. If you create your figure and plot with
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca()
ax.plot(some_x_data, some_y_data)
you need to add the following line to fill the figure with the axes:
ax.set_position([0, 0, 1, 1], which='both')
This sets the axes location relative to the figure size in the following way:
[left, bottom, width, height]
So to completely fill the figure use [0, 0, 1, 1] as shown above.
So taking your code, it should look like this (using fill_figure bool to check):
def demo_tight_layout(w=10, h=6, axisoff=False, removeticks=False, fill_figure=False):
fig,ax = plt.subplots()
fig.set_facecolor((0.8, 0.8, 0.8))
rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
ax.add_patch(rect)
ax.plot([-w/2,w/2], [-h/2,h/2])
ax.plot([-w/2,w/2], [h/2,-h/2])
ax.set_ylabel("ylabel")
ax.margins(0)
_texts = []
if axisoff:
ax.set_axis_off()
_texts.append("axisoff")
if removeticks:
ax.set_xticks([])
ax.set_yticks([])
ax.set_ylabel("")
_texts.append("removeticks")
fig.text(0.5, 0.6, " ".join(_texts))
fig.tight_layout(pad=0)
if fill_figure:
ax.set_position([0, 0, 1, 1], which='both')
plt.show()
return fig, ax, text
ax.set_position needs to be after fig.tight_layout.
If a figure title is needed, there is no direct way to do it. This unluckily can't be avoided. You need to adapt the height parameters manually so that the title fits in the figure, for example with:
ax.set_position([0, 0, 1, .9], which='both')

matplotlib bar plot spacings

I'm trying to plot 3 bars per value of N. The data is:
N=['A','B','C','D','E','F']
SF = (0.87,9.4,49,110,820,1752)
IRT = (0.34,25,210,487,2861,5541)
IRTO = (0.5,33,271,568,3031,6314)
These numbers of w (width), y_pos and figsize are basically just trial and error until it looks decent enough to my eye...
w = 1
y_pos = 4*np.arange(len(N))
fig, ax = plt.subplots(figsize=(10,5))
rects1 = ax.bar(y_pos - w, SF, align='center', alpha=0.7, width=w, color="lightgrey", log=True)
rects2 = ax.bar(y_pos , IRT, align='center', alpha=1.0, width=w, color="grey", log=True)
rects3 = ax.bar(y_pos + w, IRTO, align='center', alpha=1.0, width=w, color="black", log=True)
plt.xticks(y_pos,N,fontsize=13)
legend = ax.legend((rects1[0], rects2[0], rects3[0]), ('SF', 'IRT', 'IRTO'), loc='upper left')
plt.show()
All that produces the following plot:
This is pretty good, unfortunately I like to to make everything as perfect as possible so I want to do basically 4 thins:
reduce the space between the left axis and the first bar (and the last bar and the right axis).
increase the size of the top axis so that the highest bar is not as close to it
remove the middle ticks over the lower axis
add the blue ticks (between the bars) - see figure below:
I really tried to do this, but I couldnt find a way to do it yet.
I was able to do number 3 alone, but not number 4.
Thanks!

Representing the iterative development of steady state in matplotlib

I would like to use matplotlib to generate a graph similar to this one:
In my case, I in fact have two equations, one linear, one roughly a rectangular hyperbola, and I would like to show the iterative process by which a steady state of period two evolves. I can graph the two functions easily, but adding line segments with arrows that demonstrate the oscillation between the curves via the diagonal x=y I cannot figure out, nor how to attach a second y-axis directly below the first that shows the development of the steady-state over time.
The dictionary references are to variables that determine the exact shape of the functions. I am particularly wondering how to draw line segments as in the below graph, assuming I can generate the necessary coordinates.
Additionally, attaching a second y-axis directly below the first (but perhaps this should be a separate question).
def rot_time_series(self):
fig = plt.figure(figsize=(10, 10), frameon = False)
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
x_vals = np.arange(0,100,0.1)
values = np.empty([len(x_vals), 3])
for i in range(len(x_vals)):
y_A = self.mp['cA']['a'] * x_vals[i] + self.mp['cA']['b'] * x_vals[i] / (self.mp['cA']['c'] + x_vals[i])
y_B = self.mp['cB']['a'] * x_vals[i]
values[i,0] = x_vals[i]
values[i, 1] = y_A
values[i, 2] = y_B
#mplot.rc('text', usetex=True)
mplot.rc('font', family='serif')
ax1.set_xlabel(r'$N_t$')
ax1.set_ylabel(r'$N_{t+1}$')
ax1.plot(values[:,0], values[:,0], color="black", linewidth=2, linestyle="-")
ax1.plot(values[:,0], values[:,1], color="blue", linewidth=2, linestyle="--")
ax1.plot(values[:,0], values[:,2], color="red", linewidth=2, linestyle="-.")
plt.show()