Independent axis for each subplot in pandas boxplot

前端 未结 3 997
孤城傲影
孤城傲影 2021-01-06 10:06

The below code helps in obtaining subplots with unique colored boxes. But all subplots share a common set of x and y axis. I was looking forward to having independent axis f

相关标签:
3条回答
  • 2021-01-06 10:38

    If you really think it is necessary to un-share the axes after the creation of the boxplot array, you can do this, but you have to do everything 'by hand'. Searching a while through stackoverflow and looking at the matplotlib documentation pages I came up with the following solution to un-share the yaxes of the Axes instances, for the xaxes, you would have to go analogously:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.patches import PathPatch
    from matplotlib.ticker import AutoLocator, AutoMinorLocator
    
    ##using differently scaled data for the different random series:
    df = pd.DataFrame(
        np.asarray([
            np.random.rand(140),
            2*np.random.rand(140),
            4*np.random.rand(140),
            8*np.random.rand(140),
        ]).T,
        columns=['A', 'B', 'C', 'D']
    )
    
    df['models'] = pd.Series(np.repeat([
        'model1','model2', 'model3', 'model4',   'model5', 'model6', 'model7'
    ], 20))
    
    ##creating the boxplot array:
    bp_dict = df.boxplot(
        by="models",layout = (2,2),figsize=(6,8),
        return_type='both',
        patch_artist = True,
        rot = 45,
    )
    
    colors = ['b', 'y', 'm', 'c', 'g', 'b', 'r', 'k', ]
    
    ##adjusting the Axes instances to your needs
    for row_key, (ax,row) in bp_dict.items():
        ax.set_xlabel('')
    
        ##removing shared axes:
        grouper = ax.get_shared_y_axes()
        shared_ys = [a for a in grouper]
        for ax_list in shared_ys:
            for ax2 in ax_list:
                grouper.remove(ax2)
    
        ##setting limits:
        ax.axis('auto')
        ax.relim()      #<-- maybe not necessary
    
        ##adjusting tick positions:
        ax.yaxis.set_major_locator(AutoLocator())
        ax.yaxis.set_minor_locator(AutoMinorLocator())
    
        ##making tick labels visible:    
        plt.setp(ax.get_yticklabels(), visible=True)
    
        for i,box in enumerate(row['boxes']):
            box.set_facecolor(colors[i])
    
    plt.show()
    

    The resulting plot looks like this:

    Explanation:

    You first need to tell each Axes instance that it shouldn't share its yaxis with any other Axis instance. This post got me into the direction of how to do this -- Axes.get_shared_y_axes() returns a Grouper object, that holds references to all other Axes instances with which the current Axes should share its xaxis. Looping through those instances and calling Grouper.remove does the actual un-sharing.

    Once the yaxis is un-shared, the y limits and the y ticks need to be adjusted. The former can be achieved with ax.axis('auto') and ax.relim() (not sure if the second command is necessary). The ticks can be adjusted by using ax.yaxis.set_major_locator() and ax.yaxis.set_minor_locator() with the appropriate Locators. Finally, the tick labels can be made visible using plt.setp(ax.get_yticklabels(), visible=True) (see here).

    Considering all this, @DavidG's answer is in my opinion the better approach.

    0 讨论(0)
  • 2021-01-06 10:55

    You need to create the figure and subplots before hand and pass this in as an argument to df.boxplot(). This also means you can remove the argument layout=(2,2):

    fig, axes = plt.subplots(2,2,sharex=False,sharey=False)
    

    Then use:

    bp_dict = df.boxplot(
    by="models", ax=axes, figsize=(6,4),
    return_type='both',
    patch_artist = True,
    )
    
    0 讨论(0)
  • 2021-01-06 10:55

    You may set the ticklabels visible again, e.g. via

    plt.setp(ax.get_xticklabels(), visible=True)
    

    This does not make the axes independent though, they are still bound to each other, but it seems like you are asking about the visibilty, rather than the shared behaviour here.

    0 讨论(0)
提交回复
热议问题