在子图的seaborn boxplot上绘制观测值的数量python

问题描述

我已经定义了一个函数,可以使用箱线图分析我的列。

    fig,ax = plt.subplots((len(list_of_columns)),1,figsize= datafigsize) 
    fig.suptitle(suptitle,fontsize=30)
    ax = ax.ravel() # Ravel turns a matrix into a vector,which is easier to iterate
    plt.tight_layout(h_pad = 3,pad=10);
    
    for i,column in enumerate(list_of_columns): 
        nobs = dataframe[column].value_counts().values
        nobs = [str(y) for y in nobs.tolist()]
        nobs = ["n: " + j for j in nobs]   
        pos = range(len(nobs))
        medians = dataframe.groupby([column])['saleprice'].median().values
        for tick,label in zip(pos,ax[i].get_xticklabels()):                                   
            ax[i].text(pos[tick],medians[tick] + 0.03,nobs[tick],horizontalalignment='center',size='small',color='k',weight='semibold')
            sns.Boxplot(data = dataframe,x= dataframe[column],y='saleprice',ax=ax[i]) 
            ax[i].set_title(list_of_titles[i],fontdict={'fontsize': 15})
            ax[i].xaxis.set_visible(True);

子图工作正常。 我的观察数也被标绘。

但是,观察值的数量只能按6个类别绘制。这是一个示例:

显示6个类别的n =#。

显示6个类别的n =#。

解决方法

环境中很可能存在其他一些引起问题的对象。还将sns.boxplot放置在错误的for循环中。

如果我使用示例数据集进行设置:

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

Vars = [i for i in string.ascii_letters]
np.random.seed(111)
dataframe = pd.DataFrame({'saleprice':np.random.uniform(0,100,100),'var1':np.random.choice(Vars[0:5],'var2':np.random.choice(Vars[5:12],'var3':np.random.choice(Vars[12:21],100)})

list_of_columns = ['var1','var2','var3']

您可以在下面看到,我对脚本进行了一些修改,计算了data.frame中观察值的中位数和数量。还要确保绘制的顺序和计数的顺序相同(我将groupby数据框的索引用作下面的参考):

for i,column in enumerate(list_of_columns): 
    stats_df = dataframe.groupby(column)['saleprice'].agg(median=np.median,n=len)
    stats_df = stats_df.sort_values('median')
    sns.boxplot(data = dataframe,x= column,y='saleprice',ax=ax[i],order=stats_df.index)
    ax[i].set_title(list_of_columns[i],fontdict={'fontsize': 15})
    
    for xpos in range(len(stats_df)):
        label = "n= "+str(stats_df['n'][xpos])
        ypos = stats_df['median'][xpos] + 0.03
        ax[i].text(xpos,ypos,label,horizontalalignment='center',size='small')

enter image description here