updating subplots in real time using pyplot - matplotlib

I recently came across a way to refresh a plot with an incoming data stream.
The gist of the script is shown below.
plt.show(block=False) fig = plt.figure()
ax = plt.imshow(data_array, cmap='Greens', interpolation='None',clim=[0, 1], origin='lower', extent=extent, aspect='auto')
for i in range(100):
updating data_array...
ax.set_array(data_array)
fig.canvas.draw()
fig.canvas.flush_events()
This worked very well for a single plot and I wanted to apply this to have two subplots being refreshed in real time.
Below is what I tried.
plt.show(block=False)
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
ax1 = plt.imshow(data_array_1, cmap='Greens', interpolation='None',clim=[0, 1], origin='lower', extent=extent, aspect='auto')
ax2 = plt.imshow(data_array_2, cmap='Greens', interpolation='None',clim=[0, 1], origin='lower', extent=extent, aspect='auto')
for i in range(100):
updating data_array_1... and data_array_2
ax1.set_array(data_array_1)
ax2.set_array(data_array_2)
fig.canvas.draw()
fig.canvas.flush_events()
Unfortunately, this ended up not working as I hoped.

Related

Cannot rotate xticks when using two y axes

For some reason, when I create a plot that uses two y-axes I can no longer rotate the xticks using plt.xticks(rotation=45). Are the xticks controlled differently when using two y-axis?
plt.figure()
ax = sns.boxplot(
data=df,
x='x',
y='y',
)
ax2 = ax.twinx()
ax2 = sns.scatterplot(
x='x',
y='y',
ax=ax2,
data=df2,
legend=False,
)
plt.tight_layout()
sns.despine(offset=10, trim=True, bottom=False, right=False)
# seems to have no effect
plt.xticks(rotation=45)
plt.show()
As commented, referencing the first axis solves the issue. The following code does what I was hoping for:
plt.figure()
ax = sns.boxplot(
data=df,
x='x',
y='y',
)
ax2 = ax.twinx()
ax2 = sns.scatterplot(
x='x',
y='y',
ax=ax2,
data=df2,
legend=False,
)
plt.tight_layout()
sns.despine(offset=10, trim=True, bottom=False, right=False)
# now rotates axis labels
ax.set_xticklabels(labels_list, rotation=45)
plt.show()

Seaborn regplot with horizontal subplots with sharey=True and showing y tick labels

I have these three regplots side by side, however, I want to do these:
-increase the size of graphs
-separate them a little bit so can see the y axis more clearly
-see the values on y axis for the two right side graphs.
does anyone know how to do it efficiently? thanks
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharey=True)
sns.regplot(x=Dem['Price'], y=Dem['A'], color="g", ax=ax1)
sns.regplot(x=Dem['Price'], y=Dem['B'], color="b", ax=ax2)
sns.regplot(x=Dem['Price'], y=Dem['C'], color="purple", ax=ax3)
You can use: fig.set_figwidth(25) to widen the figure and create space passing whatever numeric value you desire, e.g. 25.
To label the y-axis ticks of all subplots, use:
for ax in fig.axes:
ax.tick_params(axis='y', labelleft=True)
Full reproducible code sample with flights seaborn dataset:
import seaborn as sns
df = sns.load_dataset('flights')
df1 = df[df['year']==1949]
df2 = df[df['year']==1950]
df3 = df[df['year']==1951]
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharey=True)
#1
fig.set_figwidth(25)
sns.regplot(x=df1['year'], y=df1['passengers'], color="g", ax=ax1)
sns.regplot(x=df2['year'], y=df2['passengers'], color="b", ax=ax2)
sns.regplot(x=df3['year'], y=df3['passengers'], color="purple", ax=ax3)
#2
for ax in fig.axes:
ax.tick_params(axis='y', labelleft=True)
Your code:
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharey=True)
fig.set_figwidth(25)
sns.regplot(x=Dem['Price'], y=Dem['A'], color="g", ax=ax1)
sns.regplot(x=Dem['Price'], y=Dem['B'], color="b", ax=ax2)
sns.regplot(x=Dem['Price'], y=Dem['C'], color="purple", ax=ax3)
for ax in fig.axes:
ax.tick_params(axis='y', labelleft=True)

Three plot in one figure using Matplotlib

I want my plot to look like the image below, how can I achieve that using Matplotlib?
And thanks
You can use GridSpec similar to this tutorial. Possibly there will be not enough space for the y tick labels, which can be mitigated by increasing the default wspace.
import matplotlib.pyplot as plt
fig, axs = plt.subplots(ncols=4, nrows=2, figsize=(12, 7), gridspec_kw={'wspace': 0.4})
gs = axs[0, 0].get_gridspec()
for ax in axs.ravel():
ax.remove()
ax1 = fig.add_subplot(gs[0, :2])
ax1.set_ylabel('A')
ax2 = fig.add_subplot(gs[0, 2:])
ax2.set_ylabel('B')
ax3 = fig.add_subplot(gs[1, 1:3])
ax3.set_ylabel('C')
for ax in (ax1, ax2, ax3):
ax.set_xlabel('D')
ax.legend(handles=[], title='legend', loc='upper right', frameon=False)
plt.show()

Label is Missing from matplotlib legend

I'm plotting subplots with matplotlib and the legend does not show up for some plots.
In this example, the scatter plot legend does not show up.
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
from matplotlib.patches import Rectangle, Circle
fig = plt.figure()
plt.cla()
plt.clf()
x = np.arange(5) + 1
y = np.full(5, 10)
fig, subplots = plt.subplots(2, sharex=False, sharey=False)
subplots[0].bar(x, y, color='r', alpha=0.5, label='a')
scat = subplots[0].scatter(x, y-1, color='g', label='c')
subplots[0].set_yscale('log')
subplots[1].bar(x, y, color='r', alpha=0.5, label='a')
x = [2, 3]
y = [4, 4]
subplots[1].bar(x, y, color='b', alpha=1, label='b')
subplots[1].set_yscale('log')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), handler_map={scat: HandlerLine2D(numpoints=4)})
plt.show()
Here is what I tried as a workaround:
p1 = Rectangle((0, 0), 1, 1, fc="r", alpha=0.5)
p2 = Rectangle((0, 0), 1, 1, fc="b")
p3 = Circle((0, 0), 1, fc="g")
legend([p1, p2, p3], ['a', 'b', 'c'], loc='center left', bbox_to_anchor=(1, 0.5))
I really prefer to fix this without the workaround so if anyone knows how to fix it please let me know.
Also, an issue with the workaround is that the Circle object still appears as a bar on the legend.
plt.legend starts with a gca() (which returns the current axes):
# from pyplot.py:
def legend(*args, **kwargs):
ret = gca().legend(*args, **kwargs)
So calling plt.legend will only get you a legend on your last subplot. But it is also possible to call e.g. ax.legend(), or in your case subplots[0].legend(). Adding that to the end of your code gives me a legend for both subplots.
Sample:
for subplot in subplots:
subplot.legend(loc='center left', bbox_to_anchor=(1, 0.5))

matplotlib xticks labels overlap

I am not able to get nicer spaces between the xticks with the following code:
import random
import matplotlib.pyplot as plt
coverages = [random.randint(1,10)*2] * 100
contig_names = ['AAB0008r'] * len(coverages)
fig = plt.figure()
fig.clf()
ax = fig.add_subplot(111)
ax.yaxis.grid(True, linestyle='-', which='major', color='grey', alpha=0.5)
ind = range(len(coverages))
rects = ax.bar(ind, coverages, width=0.2, align='center', color='thistle')
ax.set_xticks(ind)
ax.set_xticklabels(contig_names)
#function to auto-rotate the x axis labels
fig.autofmt_xdate()
plt.show()
How to get more space between the xticks so they do not look like overlapped anymore?
Thank you in advance.
You can try changing the figure size, the size of the xticklabels, their angle of rotation, etc.
# Set the figure size
fig = plt.figure(1, [20, 8])
# Set the x-axis limit
ax.set_xlim(-1,100)
# Change of fontsize and angle of xticklabels
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')