Matplotlib: How to Create Axessubplot Objects, Then Add Them to a Figure Instance

matplotlib: can I create AxesSubplot objects, then add them to a Figure instance?

Typically, you just pass the axes instance to a function.

For example:

import matplotlib.pyplot as plt
import numpy as np

def main():
x = np.linspace(0, 6 * np.pi, 100)

fig1, (ax1, ax2) = plt.subplots(nrows=2)
plot(x, np.sin(x), ax1)
plot(x, np.random.random(100), ax2)

fig2 = plt.figure()
plot(x, np.cos(x))

plt.show()

def plot(x, y, ax=None):
if ax is None:
ax = plt.gca()
line, = ax.plot(x, y, 'go')
ax.set_ylabel('Yabba dabba do!')
return line

if __name__ == '__main__':
main()

To respond to your question, you could always do something like this:

def subplot(data, fig=None, index=111):
if fig is None:
fig = plt.figure()
ax = fig.add_subplot(index)
ax.plot(data)

Also, you can simply add an axes instance to another figure:

import matplotlib.pyplot as plt

fig1, ax = plt.subplots()
ax.plot(range(10))

fig2 = plt.figure()
fig2.axes.append(ax)

plt.show()

Resizing it to match other subplot "shapes" is also possible, but it's going to quickly become more trouble than it's worth. The approach of just passing around a figure or axes instance (or list of instances) is much simpler for complex cases, in my experience...

How to add seaborn axes to matplotlib figure with subplots?

You simply assign the axis on which you want to plot as input to the function and explicitly specify on which axis you want to plot in sns.lineplot

import pandas as pd
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt

def plotf(df_x,ax):
g = sns.lineplot(data=df_x[['2016','2017','2018']],ax=ax)
g.set_xticks(range(0,12))
g.set_xticklabels(['Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan'])
return g

df = pd.DataFrame({'Period': list(range(1,13)),
'2016': np.random.randint(low=1, high=100, size=12),
'2017': np.random.randint(low=1, high=100, size=12),
'2018': np.random.randint(low=1, high=100, size=12)})

fig, ax = plt.subplots(nrows=3)
plotf(df,ax[0])
plotf(df,ax[1])
plotf(df,ax[2])

output

What is the proper way of re-adding axes to a matplotlib figure while maintaining a constrained layout?

Using the current development version of matplotlib the error would not appear. But one would need to make sure to exclude the respective axes from the constrained layout mechanism.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(constrained_layout=True)
ax2 = fig.add_subplot(111, projection="polar")
ax2.set_visible(False)
ax2.set_in_layout(False)

def swap(evt):
if evt.key == "h":
b = ax.get_visible()
ax.set_visible(not b)
ax.set_in_layout(not b)
ax2.set_visible(b)
ax2.set_in_layout(b)
fig.canvas.draw_idle()

cid = fig.canvas.mpl_connect("key_press_event", swap)

plt.show()

With any current matplotlib version, one could use tight_layout instead of constrained layout, and call it manually at each resize event.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax2 = fig.add_subplot(111, projection="polar")
ax2.set_visible(False)

def swap(evt):
if evt.key == "h":
b = ax.get_visible()
ax.set_visible(not b)
ax2.set_visible(b)
fig.tight_layout()
fig.canvas.draw_idle()

def onresize(evt):
fig.tight_layout()

cid = fig.canvas.mpl_connect("key_press_event", swap)
cid = fig.canvas.mpl_connect("resize_event", onresize)
fig.tight_layout()
plt.show()

Use function to create plot objects, then place them into figure

Are you sure that you didn't have a small mistake in your first attempt. The following works fine for me.

import numpy as np
import matplotlib.pyplot as plt

n1 = 5
n2 = 30

x1 = np.linspace(0,10,n1)
y1 = np.random.rand(n1)
x2 = np.linspace(0,10,n2)
y2 = np.random.rand(n2)

#Matplotlib example copy paste
def my_plotter(ax, data1, data2):
out = ax.plot(data1, data2)
return out

fig, (ax1, ax2) = plt.subplots(1, 2)
my_plotter(ax1, x1, y1)
my_plotter(ax2, x2, y2)

plt.show()

So the question left is what is wrong with your second example. In the example listed above, we have a function which is given an axis object (ax) as well as the data. It returns that very same axis object which now has plotting on it.

You had a figure being created within the function, but that is not needed since we already have the figure created here

fig, (ax1, ax2) = plt.subplots(1, 2)

and then we markup that first ax1 with

my_plotter(ax1, x1, y1)

and then markup that second ax2 with

my_plotter(ax2, x2, y2)

And finally make sure that your function is altering the axis object. Before, you had ax.plot(). You changed to plt.scatter. Try ax.scatter() instead.

pyplot - copy an axes content and show it in a new figure

Copying the axes

The inital answer here does not work, we keep it for future reference and also to see why a more sophisticated approach is needed.

#There are some pitfalls on the way with the initial approach. 

#Adding an `axes` to a figure can be done via `fig.add_axes(axes)`. However, at this point,

#the axes' figure needs to be the figure the axes should be added to.

#This may sound a bit like running in circles but we can actually set the axes'

#figure as `axes.figure = fig2` and hence break out of this.

#One might then also position the axes in the new figure to take the usual dimensions.

#For this a dummy axes can be added first, the axes can change its position to the position

#of the dummy axes and then the dummy axes is removed again. In total, this would look as follows.

import matplotlib.pyplot as plt

import numpy as np

num_rows = 10

num_cols = 1

fig, axs = plt.subplots(num_rows, num_cols, sharex=True)

for i in xrange(num_rows):

ax = axs[i]

ax.plot(np.arange(10), np.arange(10)**i)





def on_click(event):

axes = event.inaxes

if not axes: return

fig2 = plt.figure()

axes.figure=fig2

fig2.axes.append(axes)

fig2.add_axes(axes)



dummy = fig2.add_subplot(111)

axes.set_position(dummy.get_position())

dummy.remove()

fig2.show()

fig.canvas.mpl_connect('button_press_event', on_click)

plt.show()

#So far so good, however, be aware that now after a click the axes is somehow

#residing in both figures, which can cause all sorts of problems, e.g. if you

# want to resize or save the initial figure.

matplotlib: can I create AxesSubplot objects, then add them to a Figure instance?

Typically, you just pass the axes instance to a function.

For example:

import matplotlib.pyplot as plt
import numpy as np

def main():
x = np.linspace(0, 6 * np.pi, 100)

fig1, (ax1, ax2) = plt.subplots(nrows=2)
plot(x, np.sin(x), ax1)
plot(x, np.random.random(100), ax2)

fig2 = plt.figure()
plot(x, np.cos(x))

plt.show()

def plot(x, y, ax=None):
if ax is None:
ax = plt.gca()
line, = ax.plot(x, y, 'go')
ax.set_ylabel('Yabba dabba do!')
return line

if __name__ == '__main__':
main()

To respond to your question, you could always do something like this:

def subplot(data, fig=None, index=111):
if fig is None:
fig = plt.figure()
ax = fig.add_subplot(index)
ax.plot(data)

Also, you can simply add an axes instance to another figure:

import matplotlib.pyplot as plt

fig1, ax = plt.subplots()
ax.plot(range(10))

fig2 = plt.figure()
fig2.axes.append(ax)

plt.show()

Resizing it to match other subplot "shapes" is also possible, but it's going to quickly become more trouble than it's worth. The approach of just passing around a figure or axes instance (or list of instances) is much simpler for complex cases, in my experience...



Related Topics



Leave a reply



Submit