0

Below shown is the categorical data detail for the bar chart, which is from a specific DataFrame column i.e. coast

import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt


IN: data['coast'].dtypes
OUT: 
CategoricalDtype(categories=[0, 1], ordered=False)


IN: data['coast'].value_counts()  
OUT: 
0    21450
1      163
Name: coast, dtype: int64

Shown below syntax is the defined function used, to get the bar chart.

def code(c):
    plt.rc('figure', figsize=(10, 5))
        
    ax = c.value_counts().plot(kind='bar')
    
    for value in ax:
        height = value.get_height()
        plt.text(value.get_x() + value.get_width()/2., 
                 1.002*height,'%d' % int(height), ha='center', va='bottom')
   

However, the bar chart does appears without the values on the bar which is shown below.

IN: code(data['coast'])
OUT:

enter image description here

But the below error message appears

---------------------------------------------------------------------------
TypeError: 'AxesSubplot' object is not iterable
---------------------------------------------------------------------------

How could I resolve the above error to get the below bar chart.

enter image description here

markwalker_
  • 12,078
  • 7
  • 62
  • 99
WF30
  • 213
  • 1
  • 3
  • 16
  • `ax` contains the plot, not the data. Have a look [here](https://stackoverflow.com/questions/25447700/annotate-bars-with-values-on-pandas-bar-plots) for annotating bar charts. – mozway Jul 10 '21 at 18:03
  • 2
    Does this answer your question? [Annotate bars with values on Pandas bar plots](https://stackoverflow.com/questions/25447700/annotate-bars-with-values-on-pandas-bar-plots) – mozway Jul 10 '21 at 18:03
  • I believe you meant to iterate over `ax.patches` – Henry Ecker Jul 10 '21 at 18:04
  • 1
    @Henry Ecker: or maybe over the `value_counts`? – mozway Jul 10 '21 at 18:05
  • 2
    `for value in ax.patches:` will behave as expected with no further modifications. But any of the options in the duplicate work. – Henry Ecker Jul 10 '21 at 18:05
  • I actually think you want a [`sns.countplot`](https://seaborn.pydata.org/generated/seaborn.countplot.html) not `DataFrame.plot`/`value_counts` -> `ax = sns.countplot(data=df, x='coast')` if you want separate bar colors like that. – Henry Ecker Jul 10 '21 at 18:12
  • @HenryEcker I tried using the searborn, it didn't work. I faced an issue as well. Appreciate if you could look into this [link](https://stackoverflow.com/questions/68327272/bar-chat-plotting-issue-posx-and-posy-should-be-finite-values) :) – WF30 Jul 10 '21 at 18:39
  • 1
    I'm unclear on the issue in either this or the previous question as my answer does not differ from either of the answers on [your first question](https://stackoverflow.com/q/68320207/15497888). My answer would be near identical to [tdy's](https://stackoverflow.com/a/68322925/15497888) who goes through how to use either `countplot` or `catplot` – Henry Ecker Jul 10 '21 at 18:45

1 Answers1

1

As @Henry Ecker commented, you should be iterating over ax.patches. The pandas plot function is returning the axis not the patches/rectangles.

enter image description here

df = pd.DataFrame({
    'coast': np.random.choice(['Cat1','Cat2'], size=20000, p=[0.9, 0.1])
})

def code(c):
    plt.rc('figure', figsize=(10, 5))
        
    ax = c.value_counts().plot(kind='bar')
    
    for value in ax.patches:
        height = value.get_height()
        plt.text(value.get_x() + value.get_width()/2., 
                 1.002*height,'%d' % int(height), ha='center', va='bottom')

code(df.coast)

Alternatively, just make the plot and get your own value counts. The X axis for bar charts is just an array 0 to number of bars (2 in this case).

enter image description here

df = pd.DataFrame({
    'coast': np.random.choice(['Cat1','Cat2'], size=20000, p=[0.9, 0.1])
})

def code(c):
    plt.rc('figure', figsize=(10, 5))
    counts = c.value_counts()    
    ax = counts.plot(kind='bar')

    for i in range(len(counts)):
        ax.text(
            x = i,
            y = counts[i] + 600,
            s = str(counts[i]),
            ha = 'center', fontsize = 14
        )
    ax.set_ylim(0,25000)

code(df.coast)
Coup
  • 695
  • 4
  • 6