Search code examples
pythonseabornfacet-grid

Facetgrid Formatting and sorting each graph


Below is the code I've created to run the facetgrid graph. As you can see, merged1 is the first dataframe and merged2 is the second dataframe I am iterating on. There are two things I am trying to accomplish.

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

# initialize list of lists
data = [['tom', 5000, 200,5, 900 ], ['tom', 7000, 500,5, 900 ], ['nick', 7000,300,4 ,4000], ['nick', 8000,200,4 ,4000], ['juli',9000,300,2, 8000,], ['juli',15000,300,2, 8000,], ['TEST',10000,300,3,8000], ['TEST',8000,800,3,8000],['hang', 5000, 330,1.6,5000 ], ['hang', 1000, 330,5,5000 ]]
 
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['Donor', 'Days-post-ARV','CD4', 'VL','Days Post-COLDATE'])

#creating two separate datframes
merged1=df.drop(columns=['CD4'])
merged2=df.drop(columns=['VL'])

#function for reference vertical line 
def vertical_mean_line(x, **kwargs):
    plt.axvline(x.mean(), **kwargs)  

#for the first dataframe    
g = sns.relplot(data=merged1, x='Days-post-ARV', y='VL', col='Donor',col_wrap=3, kind="line", height=4, aspect=1.5,
                color='b')
#for the vertical line
g.map(vertical_mean_line, 'Days Post-COLDATE',ls="--",color='g')

#for the second dataframe
for patid, ax in g.axes_dict.items():  # axes_dict is new in seaborn 0.11.2
    ax1 = ax.twinx()
    sns.lineplot(data=merged2[merged2['Donor'] == patid], x='Days-post-ARV', y='CD4', color='r', ax=ax1)
    ax1.set_ylim(0,1200)

g.add_legend()   
g.tight_layout()

  1. What's the best way to sort the graph? I'd like to switch the order of the second and third graph.
  2. When plotting, the Y-axis between each graph gets merged and seeing only the 'CD4' between each graph, but there is the first Y-axis label 'VL' that should be showing up. How can I do this?enter image description here

Solution

  • Well, the test data and the original test code give:

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    
    # initialize list of lists
    data = [['tom', 5000, 200, 5, 900], ['tom', 7000, 500, 5, 900], ['nick', 7000, 300, 4, 4000], ['nick', 8000, 200, 4, 4000], ['juli', 9000, 300, 2, 8000, ], ['juli', 15000, 300, 2, 8000, ], ['TEST', 10000, 300, 3, 8000], ['TEST', 8000, 800, 3, 8000], ['hang', 5000, 330, 1.6, 5000], ['hang', 1000, 330, 5, 5000]]
    # Create the pandas DataFrame
    df = pd.DataFrame(data, columns=['Donor', 'Days-post-ARV', 'CD4', 'VL', 'Days Post-COLDATE'])
    
    # creating two separate datframes
    merged1 = df
    merged2 = df
    
    # function for reference vertical line
    def vertical_mean_line(x, **kwargs):
         plt.axvline(merged1[x].mean(), **kwargs)
    
    # for the first dataframe
    g = sns.relplot(data=merged1, x='Days-post-ARV', y='VL', col='Donor', col_wrap=3, kind="line", height=4, aspect=1.5,
                    color='b')
    # for the vertical line
    g.map(vertical_mean_line, x='Days-post-ARV', ls="--", color='g')
    
    # for the second dataframe
    for patid, ax in g.axes_dict.items():  # axes_dict is new in seaborn 0.11.2
         ax1 = ax.twinx()
         sns.lineplot(data=merged2[merged2['Donor'] == patid], x='Days-post-ARV', y='CD4', color='r', ax=ax1)
         ax1.set_ylim(0, 1200)
    g.add_legend()
    g.tight_layout()
    plt.show()
    

    You'll notice the order of the subplots is the same as the order the donors appear in the dataframe: ['tom', 'nick', 'juli', 'TEST', 'hang'].

    sns.relplot original

    It seems Seaborn not only removes the left y label, it also sets it invisible. You'll need to set it visible again. Note that changes to ax influence the left ticks and left labels, while changes to ax1 influence the ticks and the labels at the right of the subplots.

    Changing the code to add a new col_order. And adding ax.set_ylabel('VL', visible=True):

    
    # for the first dataframe, NEW col_order
    g = sns.relplot(data=merged1, x='Days-post-ARV', y='VL', col='Donor', col_wrap=3, kind="line", height=4, aspect=1.5,
                    color='b', col_order=['tom', 'juli', 'nick', 'TEST', 'hang'])
    # for the vertical line
    g.map(vertical_mean_line, x='Days-post-ARV', ls="--", color='g')
    
    # for the second dataframe
    for patid, ax in g.axes_dict.items():  # axes_dict is new in seaborn 0.11.2
         ax1 = ax.twinx()
         sns.lineplot(data=merged2[merged2['Donor'] == patid], x='Days-post-ARV', y='CD4', color='r', ax=ax1)
         ax1.set_ylim(0, 1200)
         ax.set_ylabel('VL', visible=True) # ADDED
    
    g.add_legend()
    g.tight_layout()
    plt.show()
    

    new sns.relplot