0

I have a question that is very similar but not exactly the same as this and this questions.

I have 2 pyplot.subplots() generating fig and ax objects, and I would like to add the last one to the last position of the first fig.

import matplotlib.pyplot as plt
import seaborn as sns

df = pd.DataFrame({'a' :['one','one','two','two','one','two','one','one','one','two'], 'b': [1,2,1,2,1,2,1,2,1,1], 'c': [1,2,3,4,6,1,2,3,4,6]})


fig, ax = plt.subplots(ncols=3)
ax=ax.flatten()

for i in [0,1,2]:
    if(i<2):
        myvar=["b","c"][i]
        sns.boxplot( data=df,
            x='a', y=myvar, ax=ax[i])

### some other fig
fig2,ax2 = plt.subplots(figsize=(4,5))
g=sns.scatterplot(data=df, x='b', y='c')

### I have tried the following, but both of which return only the last figure generated
fig.axes.append(ax2) #
# or:
ax[2]=ax2

# I have also tried the following, but this returns an error:
#fig.add_axes(ax2)


plt.show() 

Edit: Further, would it be possible to do this appending should the last figure have multiple rows or columns?

Sos
  • 1,783
  • 2
  • 20
  • 46
  • What do you mean 'add'? as in you want ax2 to be plotted within ax[2]? Seems if that was the case you could just add `else: sns.scatterplot(data=df, x='b', y='c')` to your for loop – Michael Green Aug 04 '20 at 18:21
  • Exactly. Or, in a more complex setting, I'd like `n` additional axes from `fig2` to be added to `ax[2]` to `ax[n+2]` (in this case, one could initially set `fig,ax=plt.subplots(ncols=2+n)`. – Sos Aug 04 '20 at 18:24
  • Or to make it clearer, I'm wondering what would be the case where `fig2,ax2` would have more than 1 column or row or column/row – Sos Aug 04 '20 at 18:24
  • 1
    Did you check the second answer to the first question you linked? This is not possible in newer versions of matplotlib. As it says in that answer "axes cannot live in several figures at once". So you would need to remove it from one and add to the other. I would think that's more hassle than its worth - it would be better to just have a function which takes an axes instance as the input which does the plotting, then you can pass in an axes from fig and later from fig2 to get the same plot on each figure. – tmdavison Aug 04 '20 at 19:48
  • hi @tmdavison would you mind putting your suggestion as an answer? – Sos Aug 05 '20 at 07:56
  • 1
    @Sos there you go :) – tmdavison Aug 05 '20 at 09:12

2 Answers2

0

sns.scatterplot() has an ax parameter. You could do like following

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd


df = pd.DataFrame({'a' :['one','one','two','two','one','two','one','one','one','two'], 'b': [1,2,1,2,1,2,1,2,1,1], 'c': [1,2,3,4,6,1,2,3,4,6]})

fig, ax = plt.subplots(ncols=3)
ax=ax.flatten()

for i in [0,1,2]:
    if(i<2):
        myvar=["b","c"][i]
        sns.boxplot( data=df,
            x='a', y=myvar, ax=ax[i])

sns.scatterplot(data=df, x='b', y='c', ax=ax[2])

plt.show() 
Ynjxsjmh
  • 28,441
  • 6
  • 34
  • 52
  • Hi @Ynjxsjmh, this does not help. I am aware that `sns.scatterplot()` has an `ax` parameter. But as I mentioned, I have two functions that, independently, are producing `fig` and `ax` objects already, and my question is about adding one to the other. – Sos Aug 05 '20 at 07:52
0

In the second answer to the first question you linked (by @ImportanceofBeingErnest), it suggests added an existing axis to a different figure is not possible in newer versions of matplotlib.

As it says in that answer "axes cannot live in several figures at once". So you would need to remove it from one and add to the other. I would think that's more hassle than its worth - it would likely be better to just have a function which takes an axes instance as the input which does the plotting, then you can pass in an axes from fig and later from fig2 to get the same plot on each figure.

A quick example of how I think it could work for your code (untested, but hopefully you get the idea):

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

df = pd.DataFrame({'a': ['one', 'one', 'two', 'two', 'one', 'two', 'one', 'one', 'one', 'two'],
                   'b': [1, 2, 1, 2, 1, 2, 1, 2, 1, 1],
                   'c': [1, 2, 3, 4, 6, 1, 2, 3, 4, 6]})

# First fig
fig, ax = plt.subplots(ncols=3)
ax = ax.flatten()

# Some other fig
fig2, ax2 = plt.subplots(figsize=(4, 5))

def myboxplot(ax, df, myvar):
    ''' A function that takes the Axes instance as an input an plots a boxplot '''
    sns.boxplot(data=df, x='a', y=myvar, ax=ax)

def myscatterplot(ax, df):
    ''' A function that takes the Axes instance as an input an plots a scatterplot '''
    g=sns.scatterplot(data=df, x='b', y='c', ax=ax)

# Call the first function for the first 2 axes
myboxplot(ax[0], df, 'b') 
myboxplot(ax[1], df, 'c')

# Call the scatterplot function for an axes on the first fig
myscatterplot(ax[2], df)

# Call the scatterplot function for an axes on the second fig
myscatterplot(ax2, df)

plt.show() 
tmdavison
  • 64,360
  • 12
  • 187
  • 165