2017-06-26 8 views
5

snsのバープロットで、グループごとの相対的なパーセンテージと合計の頻度を表示しようとしています。私が比較している2つのグループはサイズが非常に異なっているため、以下の関数でグループ別のパーセンテージを表示しています。頻度とパーセントの不均一なグループsns barplot

私が作成したサンプルデータフレームの構文は、ターゲットカテゴリ変数( 'item')内のデータ( 'groups')と同様の相対グループサイズを持ちます。 'rand'は私がdfを作るために使う変数です。

# import pandas and seaborn 
import pandas as pd 
import seaborn as sns 
import numpy as np 

# create dataframe 
foobar = pd.DataFrame(np.random.randn(100, 3), columns=('groups', 'item', 'rand')) 

# get relative groupsizes 
for row, val in enumerate(foobar.rand) : 
    if val > -1.2 : 
     foobar.loc[row, 'groups'] = 'A' 
    else: 
     foobar.loc[row, 'groups'] = 'B' 

    # assign categories that I am comparing graphically 
    if row < 20: 
     foobar.loc[row, 'item'] = 'Z' 
    elif row < 40: 
     foobar.loc[row, 'item'] = 'Y' 
    elif row < 60: 
     foobar.loc[row, 'item'] = 'X' 
    elif row < 80: 
     foobar.loc[row, 'item'] = 'W' 
    else: 
     foobar.loc[row, 'item'] = 'V' 

これは、相対頻度をグループごとに比較した関数です。いくつかのデフォルト変数がありますが、私はこの質問のためにそれらを再割り当てしました。

def percent_categorical(item, df=IA, grouper='Active Status') : 
    # plot categorical responses to an item ('column name') 
    # by percent by group ('diff column name w categorical data') 
    # select a data frame (default is IA) 
    # 'Active Status' is default grouper 

    # create df of item grouped by status 
    grouped = (df.groupby(grouper)[item] 
    # convert to percentage by group rather than total count 
       .value_counts(normalize=True) 
       # rename column 
       .rename('percentage') 
       # multiple by 100 for easier interpretation 
       .mul(100) 
       # change order from value to name 
       .reset_index() 
      .sort_values(item)) 

    # create plot 
    PercPlot = sns.barplot(x=item, 
         y='percentage', 
         hue=grouper, 
         data=grouped, 
         palette='RdBu' 
         ).set_xticklabels(
           labels = grouped[item 
             ].value_counts().index.tolist(), rotation=90) 
    #show plot 
    return PercPlot 

機能やグラフのフォローを結果:

percent_categorical('item', df=foobar, grouper='groups') 

result of running my function

それは私がグループで相対的な割合を示したことができますので、これは、良いです。しかし、私はまた、各グループの絶対数を、凡例に表示することをお勧めします。この場合、グループAの全メンバーが89人、グループBの合計メンバーが11人いることを示したいと思います。

ありがとうございました。

答えて

4

groupby操作を分割して解決しました.1つはパーセンテージを取得し、もう1つはオブジェクトの数をカウントします。

次のように私はあなたのpercent_catergorical機能を調整する:

def percent_categorical(item, df=IA, grouper='Active Status') : 
    # plot categorical responses to an item ('column name') 
    # by percent by group ('diff column name w categorical data') 
    # select a data frame (default is IA) 
    # 'Active Status' is default grouper 

    # create groupby of item grouped by status 
    groupbase = df.groupby(grouper)[item] 
    # count the number of occurences 
    groupcount = groupbase.count()  
    # convert to percentage by group rather than total count   
    groupper = (groupbase.value_counts(normalize=True) 
       # rename column 
       .rename('percentage') 
       # multiple by 100 for easier interpretation 
       .mul(100) 
       # change order from value to name 
       .reset_index() 
       .sort_values(item)) 

    # create plot 
    fig, ax = plt.subplots() 
    brplt = sns.barplot(x=item, 
         y='percentage', 
         hue=groupper, 
         data=groupper, 
         palette='RdBu', 
         ax=ax).set_xticklabels(
           labels = grouper[item 
             ].value_counts().index.tolist(), rotation=90) 
    # get the handles and the labels of the legend 
    # these are the bars and the corresponding text in the legend 
    thehandles, thelabels = ax.get_legend_handles_labels() 
    # for each label, add the total number of occurences 
    # you can get this from groupcount as the labels in the figure have 
    # the same name as in the values in column of your df 
    for counter, label in enumerate(thelabels): 
     # the new label looks like this (dummy name and value) 
     # 'XYZ (42)' 
     thelabels[counter] = label + ' ({})'.format(groupcount[label]) 
    # add the new legend to the figure 
    ax.legend(thehandles, thelabels) 
    #show plot 
    return fig, ax, brplt 

をあなたの姿を取得するには:

fig, ax, brplt = percent_categorical('item', df=foobar, grouper='groups') 

結果のグラフは次のようになります。あなたが変更することができ

the output

あなたが望むようにこの伝説の表情、私はちょうどいいですd括弧を例に挙げる。

+0

ありがとうございます! 'brplt ='コマンドで の場合、 'grouped'の両方のインスタンスを 'groupper'に切り替える必要があります。この変更により、これは完全に機能します。 – Andrew

+0

@Andrewの頭のおかげで! – Daan