mjoy
mjoy

Reputation: 680

How to create one figure from plot results of for loop

I have a dataframe that looks like

id         a1    a2     a3    a4    a5    a6   value1     value2
 1         .2    .3    .4     .2   .1     .2     1         0
 2         .1    .2    .1     .3   .7     .3     1         1
 3         .4    .1    .1     .1   .5     .4     0         0
 4         .5    .3    .3     .4   .6     .1     0         1
 5         .3    .1    .1     .3   .2     .3     0         1
 6         .7    .2    .3     .3   .6     .1     0         0
 7         .2    .6    .8     .1   .2     .4     1         1
 8         .1    .4    .2     .1   .9     .3     0         1
 9         .4    .2    .1     .3   .5     .2     1         0
 
cols = ['a1', 'a2', 'a3', 'a4', 'a5', 'a6']
titles = []

for x in cols:
    
    g = sns.lmplot(x = x,
           y = 'value1', 
           data = data,
           scatter_kws={"color": "black"}, line_kws={"color": "blue"})

    title = x + 'val1'
    g.set(title = title)
    titles.append(title)
    plt.show()


    g = sns.lmplot(x = x,
                   y = 'value2', 
                   data = data,
                   scatter_kws={"color": "black"}, line_kws={"color": "blue"})
    title = x + 'val2'
    g.set(title = title)
    titles.append(title)
    plt.show()

This shows me each figure under each other. I want to create a figure that has all 8 plots in a 4 by 2 column but there is text on top of the columns and text to the right of each plot. Like so:

plot I have tried using

fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(3, 2)

for ax in fig.get_axes():
    ax.label_outer()

Ideally, I am looking for the plots with the title and side labvels. But just the figure with plots would be great. But I don't know how to incorporate this with the code I am using to generate the plots.

Upvotes: 1

Views: 236

Answers (1)

JohanC
JohanC

Reputation: 80279

To create an lmplot for the complete dataframe, the data needs to be in long form. As there are two sets of columns, pd.melt() needs to be called twice, taking care the columns of melted dataframe get different names. These names will then be used for the col and row of the created FacetGrid.

The code below chooses fig and ai for the melted columns of a1..a6. And val and value for the melted version of value1 and value2. You 'll probably want to choose different names, consistent with how you want to present your data.

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from io import StringIO

data_str = '''id         a1    a2     a3    a4    a5    a6   value1     value2
 1         .2    .3    .4     .2   .1     .2     1         0
 2         .1    .2    .1     .3   .7     .3     1         1
 3         .4    .1    .1     .1   .5     .4     0         0
 4         .5    .3    .3     .4   .6     .1     0         1
 5         .3    .1    .1     .3   .2     .3     0         1
 6         .7    .2    .3     .3   .6     .1     0         0
 7         .2    .6    .8     .1   .2     .4     1         1
 8         .1    .4    .2     .1   .9     .3     0         1
 9         .4    .2    .1     .3   .5     .2     1         0'''
df = pd.read_csv(StringIO(data_str), delim_whitespace=True)
df1 = df.melt(value_vars=['a1', 'a2', 'a3', 'a4', 'a5', 'a6'], var_name='fig', value_name='ai',
              id_vars=['value1', 'value2'])
df2 = df1.melt(value_vars=['value1', 'value2'], var_name='val', value_name='value', id_vars=['fig', 'ai'])

g = sns.lmplot(x='ai',
               y='value',
               row='fig',  # 'value1', 'value2'
               col='val',  # 'a1', 'a2', 'a3', 'a4', 'a5', 'a6'
               height=1.3,
               aspect=4,
               data=df2,
               scatter_kws={"color": "black"}, line_kws={"color": "blue"}, )
g.fig.subplots_adjust(left=0.06, bottom=0.06)  # a bit more space for the labels
plt.show()

sns.lmplot on melted dataframe

The melted dataframe looks like:

    fig   ai     val  value
0    a1  0.2  value1      1
1    a1  0.1  value1      1
2    a1  0.4  value1      0
3    a1  0.5  value1      0
4    a1  0.3  value1      0
..   ..  ...     ...    ...
103  a6  0.3  value2      1
104  a6  0.1  value2      0
105  a6  0.4  value2      1
106  a6  0.3  value2      1
107  a6  0.2  value2      0

Upvotes: 1

Related Questions