Adding legend by list within subplot Matplotlib - python

I want to plot 2 different graphs in one plot. One graph is just one line, so no problem with labeling the legend. In df_2_plot is a list of tickers that is delivered, so more lines and more tickers within legend. If I label them like this, I only receive the list several times in the legend, instead of the right ticker for each line.
I tried to work with for loops but can't find a solution.
def func_plot_DataFrame(df_2_plot, legend_lst):
y1 = df_2_plot
y2 = df_infektionsgeschehen
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(y1, label = legend_lst)
ax2.plot(y2, 'grey', linewidth=2, alpha=0.3, label = 'Neuinfektionen')
plt.show()

You need to use ax1.legend instead of using the label argument directly in ax1.plot
ax1.legend(labels=legend_lst)
Have a look at the official documentation here

Related

Plots in a loop in two separate figures

I have a loop over every month in the year and I want to produce two plots from it, relating to groups A and B. I'd like all curves for group A for the year on the same plot and all curves for B on a separate one. At the moment I can either put all of A on one plot by not plotting B at all, or make twelve plots with one for A and one for B made by every iteration. So I want this for both A and B:
If I try the below code for A and B, I get every curve on an individual plot. If I comment out the subplots lines they all get put on the same figure, both A and B. I guess there might be some plot() option instead of subplots, but plt.plot() throws an error.
fig1, ax1 = plt.subplots()
short1.cumsum().plot(title='')
text = fig1.text(0.50, 0.02,
'Totals')
fig1.tight_layout(rect=(0,.05,1,1))
plt.legend(loc = 'best')
fig2, ax2 = plt.subplots()
short2.cumsum().plot(title='')
text = fig2.text(0.50, 0.02,
'Totals')
fig2.tight_layout(rect=(0,.05,1,1))
plt.legend(loc = 'best')
This is basic and will be in docs, but I'm not sure what to google to find it. Thanks for any suggestions! :)

Remove plot from matplotlib subplot, but keep legend visible

I have a very customized subplot set up.
fig = plt.figure(figsize=(12, 10))
gs = fig.add_gridspec(nrows=2, ncols=2, width_ratios=[3, 1])
ax = fig.add_subplot(gs[:, 0])
ax3 = fig.add_subplot(gs[-1, -1])
ax4=fig.add_subplot(gs[0, 1])
This sets up 3 slots for plotting: one that takes up half the space on the left, and two smaller ones on the right. However, I only want the bottom right to actually be a plot. I want the top right to be the space where the legend for the larger plot on the left to go. I could just use the axes from ax to do this, but that shifts the whole plotting space off. Instead I thought of trying to just create ax4 and place the ax legend there.
lines = []
labels = []
for ax in fig.get_axes():
ln, la = ax.get_legend_handles_labels()
lines.extend(ln)
labels.extend(la)
legend = ax4.legend(lines, labels, labelspacing=0.1, loc=(-0.3,0.6), fontsize='xx-large')
fig.tight_layout()
This puts the legend exactly where I want it, but the blank figure shows up, which I don't want. Is it possible to accomplish what I want using this method? If not, what is my alternative? Picture below to better understand.
You can use ax4.axis('off') to make axis 4 invisible if you want to stick to your approach.
However, I don't see why you don't just skip creating axis 4 and just use fig.legend() instead of ax.legend(). Then the legend is placed outside the axis and you can then control the exact position just as you already did with the loc keyword.

Matplotlib scatter plot dual y-axis

I try to figure out how to create scatter plot in matplotlib with two different y-axis values.
Now i have one and need to add second with index column values on y.
points1 = plt.scatter(r3_load["TimeUTC"], r3_load["r3_load_MW"],
c=r3_load["r3_load_MW"], s=50, cmap="rainbow", alpha=1) #set style options
plt.rcParams['figure.figsize'] = [20,10]
#plt.colorbar(points)
plt.title("timeUTC vs Load")
#plt.xlim(0, 400)
#plt.ylim(0, 300)
plt.xlabel('timeUTC')
plt.ylabel('Load_MW')
cbar = plt.colorbar(points1)
cbar.set_label('Load')
Result i expect is like this:
So second scatter set should be for TimeUTC vs index. Colors are not the subject;) also in excel y-axes are different sites, but doesnt matter.
Appriciate your help! Thanks, Paulina
Continuing after the suggestions in the comments.
There are two ways of using matplotlib.
Via the matplotlib.pyplot interface, like you were doing in your original code snippet with .plt
The object-oriented way. This is the suggested way to use matplotlib, especially when you need more customisation like in your case. In your code, ax1 is an Axes instance.
From an Axes instance, you can plot your data using the Axes.plot and Axes.scatter methods, very similar to what you did through the pyplot interface. This means, you can write a Axes.scatter call instead of .plot and use the same parameters as in your original code:
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.scatter(r3_load["TimeUTC"], r3_load["r3_load_MW"],
c=r3_load["r3_load_MW"], s=50, cmap="rainbow", alpha=1)
ax2.plot(r3_dda249["TimeUTC"], r3_dda249.index, c='b', linestyle='-')
ax1.set_xlabel('TimeUTC')
ax1.set_ylabel('r3_load_MW', color='g')
ax2.set_ylabel('index', color='b')
plt.show()

Subplot charts plotted within a loop very squashed

I have a dataframe with ~120 features that I would like to examine by year. I am plotting each feature, x = year, y = feature value within a loop. Whilst these plot successfully, the charts are illegible as they are totally squashed.
I have tried using plt.tight_layout() and adjusting the figure size using plt.rcParams['figure.figsize'] but sadly to no avail
for i in range(len(roll_df.columns)):
plt.subplot(len(roll_df.columns), 1, i+1)
name = roll_df.columns[i]
plt.plot(roll_df[name])
plt.title(name, y=0)
plt.yticks([])
plt.xticks([])
plt.tight_layout()
plt.show()
The loop runs but all plots are so squashed on the y-axis as to become illegible:
Matplotlib will not automatically adjust the size of your figure. So if you add more subplots below each other, it will split the available space instead of extending the figure. That's why your y axes are so narrow.
You could try to define the figure size beforehand, or determine the figure size based on how many subplots you have:
n_plots = roll_df.shape[1]
fig, axes = plt.subplots(n_plots, 1, figsize=(8, 4 * n_plots), tight_layout=True)
# Then your usual part, but plot on the created axes
for i in range(n_plots):
name = roll_df.columns[i]
axes[i].plot(roll_df[name])
axes[i].title(name, y=0)
axes[i].yticks([])
axes[i].xticks([])
plt.show()

Hide axis label only, not entire axis, in Pandas plot

I can clear the text of the xlabel in a Pandas plot with:
plt.xlabel("")
Instead, is it possible to hide the label?
May be something like .xaxis.label.set_visible(False).
From the Pandas docs -
The plot method on Series and DataFrame is just a simple wrapper around plt.plot():
This means that anything you can do with matplolib, you can do with a Pandas DataFrame plot.
pyplot has an axis() method that lets you set axis properties. Calling plt.axis('off') before calling plt.show() will turn off both axes.
df.plot()
plt.axis('off')
plt.show()
plt.close()
To control a single axis, you need to set its properties via the plot's Axes. For the x axis - (pyplot.axes().get_xaxis().....)
df.plot()
ax1 = plt.axes()
x_axis = ax1.axes.get_xaxis()
x_axis.set_visible(False)
plt.show()
plt.close()
Similarly to control an axis label, get the label and turn it off.
df.plot()
ax1 = plt.axes()
x_axis = ax1.axes.get_xaxis()
x_axis.set_label_text('foo')
x_label = x_axis.get_label()
##print isinstance(x_label, matplotlib.artist.Artist)
x_label.set_visible(False)
plt.show()
plt.close()
You can also get to the x axis like this
ax1 = plt.axes()
x_axis = ax1.xaxis
x_axis.set_label_text('foo')
x_axis.label.set_visible(False)
Or this
ax1 = plt.axes()
ax1.xaxis.set_label_text('foo')
ax1.xaxis.label.set_visible(False)
DataFrame.plot
returns a matplotlib.axes.Axes or numpy.ndarray of them
so you can get it/them when you call it.
axs = df.plot()
.set_visible() is an Artist method. The axes and their labels are Artists so they have Artist methods/attributes as well as their own. There are many ways to customize your plots. Sometimes you can find the feature you want browsing the Gallery and Examples
You can remove axis labels and ticks using xlabel= or ylabel= arguments in the plot() call. For example, to remove the xlabel, use xlabel='':
df.plot(xlabel='');
To remove the x-axis ticks, use xticks=[] (for y-axis ticks, use yticks=):
df.plot(xticks=[]);
To remove both:
df.plot(xticks=[], xlabel='');

Categories

Resources