Matplotlib: How to extract vlines and fill_between data from ax objects? - python

I have a figure comprised of two x/y curves, a vline and a fill_between in Matplotlib.
My ultimate aim is displaying this figure along with 2 other figures as subplots in a 4th new figure. And I really want to avoid creating all three figures from scratch again just for this new figure with subplots.
So, I'm looking to create a 1x3 figure (subplots, 1 row, 3 columns) like this:
[fig1, fig2, fig3]
I'm almost there. I've so far been able to extract the two x/y curves from the original figure's ax object. Moving through a for loop, I've been able to rebuild most of the three figures as subplots in my new figure:
(ax_a, ax_b, ax_c are ax objects belonging to the three original figures I want to add as subplots to my new figure)
fig = plt.figure(figsize = (16,4))
ax1 = fig.add_subplot(1,3,1)
ax2 = fig.add_subplot(1,3,2)
ax3 = fig.add_subplot(1,3,3)
for ax, ref in zip(fig.axes, [ax_a, ax_b, ax_c]):
for line in ref.lines:
x = line.get_xdata()
y = line.get_ydata()
ax.plot(x,y)
ax.set_xlabel(ref.get_xlabel())
ax.set_ylabel(ref.get_ylabel())
This actually creates a 1x3 grid of my original 3 plots. It's almost perfect.
What's missing are the fill_between component and the vlines component. If I could extract those objects from ax_a, ax_b and ax_c, I'd be done. But I can't find a way to do that.
Is there a way? If not, how would you solve a problem like this?
Thanks so much in advance for any advice offered.

Related

python matplotlib mulitple figures (not subplots) on same pdf with custom arrangment

I have a collection of charts I need to put on the same pdf, but they are grouped into different subplot grids like below.
Ex. I have something like
fig, axes = plt.subplots(num_rows, num_cols)
fig2, axes2 = plt.subplots(num_rows2, num_cols2)
fig3, axes3 = plt.subplots(num_rows3, num_cols3)
# more figures
I'm trying a find a way of arranging the figures in the the pdf in a custom way, similar to what you can do with subplots,
fig, axis = plt.subplots(rows, cols)
axis[0, 0].plot(X, Y)
axis[0, 1].plot(X2, Y2)
but instead of a grid of axises it would be a grid of figures, and I could tell matplotlib which row or column each figure goes in.
Is there a way to do this? One workaround is to just have one figure and calculate the positions of all the plots manually based on which group there are in, but I'm wondering if there's something built in to matplotlib to do this.

add_axes covers previous plot

I am making a 3D plot with two sets of axes (in particular, an animation for a rotating cone).
First, I make one set of axes using fig.add_subplot, and plot the rotating cone using ax.plot.
fig=plt.figure()
ax = fig.add_subplot(111, projection="3d")
But when I add this declaration for ax2 after the above two lines (like below), I just see a white plot (no rotating cone).
fig=plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax2 = fig.add_axes(ax.get_position(), projection="3d", frame_on=False)
Can anyone help with what went wrong here? Why is what I plotted using ax get covered or erased when I declared an ax2?
Thanks!
The second plot background color is covering the first one. You can remove the background by doing:
ax2.patch.set_visible(False)
However, you will still see the second axes on top of the first one, and you will only be able to interact with the top axes and not the bottom one. Are you sure that's what you are trying to do?

Subplots Frequency Plots

I've been struggling to generate the frequency plot of 2 columns named "Country" and "Company" in my DataFrame and show them as 2 subplots. Here's what I've got.
Figure1 = plt.figure(1)
Subplot1 = Figure1.add_subplot(2,1,1)
and here I'm going to use the bar chart pd.value_counts(DataFrame['Country']).plot('barh')
to shows as first subplot.
The problem is, I cant just go: Subplot1.pd.value_counts(DataFrame['Country']).plot('barh') as Subplot1. has no attribute pd. ~ Could anybody shed some light in to this?
Thanks a million in advance for your tips,
R.
You don't have to create Figure and Axes objects separately, and you should probably avoid initial caps in variable names, to differentiate them from classes.
Here, you can use plt.subplots, which creates a Figure and a number of Axes and binds them together. Then, you can just pass the Axes objects to the plot method of pandas:
from matplotlib import pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
pd.value_counts(df['Country']).plot('barh', ax=ax1)
pd.value_counts(df['Company']).plot('barh', ax=ax2)
Pandas' plot method can take in a Matplotlib axes object and direct the resulting plot into that subplot.
# If you want a two plots, one above the other.
nrows = 2
ncols = 1
# Here axes contains 2 objects representing the two subplots
fig, axes = plt.subplots(nrows, ncols, figsize=(8, 4))
# Below, "my_data_frame" is the name of your Pandas dataframe.
# Change it accordingly for the code to work.
# Plot first subplot
# This counts the number of times each country appears and plot
# that as a bar char in the first subplot represented by axes[0].
my_data_frame['Country'].value_counts().plot('barh', ax=axes[0])
# Plot second subplot
my_data_frame['Company'].value_counts().plot('barh', ax=axes[1])

Making an odd number of subplots in Python

I'm very new to Python, and I want to plot 13 different figures all in one plot. To do this nicely, I would like to plot the first 12 figures in a 6x2 grid (this works just fine), and then plot the 13th figure below it; either the same size as the other figures and centered, or larger than the rest so that its width is equal to twice the width of the other figures and all the edges are aligned. What would be the best way to specify axes of this kind using subplots? (So far, I've just used nrows=6, ncols=2, but I think something like that won't work with an odd number of figures to plot.) The code I have so far for plotting the first 12 plots looks like this (with simple test data):
fig, axes = plt.subplots(nrows=6, ncols=2, figsize=(45,10))
for ax in axes.flat:
ax.plot([1,2,3,4])
fig.subplots_adjust(right=0.5)
How can I add a 13th figure below the others?
You can use GridSpec (link to documentation) to generate flexible axes layout.
The following code creates the desired layout and puts all Axes objects in a list for easy access.
gs00 = matplotlib.gridspec.GridSpec(7, 2)
fig = plt.figure()
axs = []
for i in range(6):
for j in range(2):
ax = fig.add_subplot(gs00[i,j])
axs.append(ax)
ax = fig.add_subplot(gs00[6,:])
axs.append(ax)

Python: Parallel coordinates subplots in subplot

I saw this example on how to create a parallel coordinate plot: Parallel Coordinates:
This creates a nice Parallel Coordinates figure, but I would like to add this plot to an already existing figure in a subplot (there should be another plot next to it in the same plot).
For the already existing figure, the figure and axes are defined as:
fig = plt.figure(figsize=plt.figaspect(2.))
ax = fig.add_subplot(1,2,1)
For the Parallel Coordinates, they suggest:
fig, axes = plt.subplots(1, dims-1, sharey=False)
How can I reconcile both initializations of the figure and the ax(es)?
One option is to create all the axes using subplots then just shift the location of the one that you don't want to have wspace=0 as is done for the Parallel Coordinate plots:
import matplotlib.pylab as plt
dims = 4
fig, axes = plt.subplots(1, dims-1 + 1, sharey=False)
plt.subplots_adjust(wspace=0)
ax1 = axes[0]
pos = ax1.get_position()
ax1.set_position(pos.translated(tx = -0.1,ty=0))
I have added 1 to the number of columns creates (leaving it explicitly -1+1) and set wspace=0 which draws all the plots adjacent to one another with no space inbetween. Take the left most axes and get the position which is a Bbox. This is nice as it gives you the ability to translate it by tx=-0.1 separating your existing figure.

Categories