2017-06-26 41 views
5

Próbuję pokazać względny procent przez grupę, jak również całkowitą częstotliwość w barnot sns. Dwie porównywane przeze mnie grupy różnią się bardzo rozmiarem, dlatego też pokazuję procent według grup w poniższej funkcji.częstotliwość i procent nierównomiernych grup sns barplot

Oto składnia dla próbki dataframe utworzonego że ma podobne rozmiary w stosunku do grupy moich danych („grupy”) Wśród docelowej kategorycznego zmiennej („punkt”). "rand" jest po prostu zmienną, której używam, aby 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' 

Oto funkcja, którą napisałem, która porównuje częstotliwości względne według grup. Ma kilka domyślnych zmiennych, ale przydzielono je do tego pytania.

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 

Funkcja i otrzymaną obserwacji wykres:

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

result of running my function

to dobrze, ponieważ pozwala mi pokazać względny procent w grupie. Jednak chcę również wyświetlić bezwzględne liczby dla każdej grupy, najlepiej w legendzie. W tym przypadku, chciałbym to pokazać, że istnieje 89 Wszystkich członków grupy A i 11 Wszystkich członków grupy B.

Z góry dziękuję za wszelką pomoc.

Odpowiedz

4

Rozwiązałem to przez dzielenie się pracą groupby: jedno, aby uzyskać procenty i jeden policzyć liczbę obiektów.

ja dostosować swoją funkcję percent_catergorical następująco:

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 

Aby otrzymać postać:

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

Uzyskany wykres wygląda następująco:

the output

można zmienić wygląd tej legendy, jak chcesz, po prostu dodam d nawiasy jako przykład.

+0

Dzięki! w poleceniu "brplt =" obie wystąpienia "zgrupowane" należy przełączyć na "zgrupowanie". Dzięki tej zmianie działa to doskonale. – Andrew

+0

Dzięki za słuchawki @Andrew! – Daan