0

I am using the following code to group bar plot in Python as follows.

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # the label locations
width = 0.35  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, men_means, width, label='Men')
rects2 = ax.bar(x + width/2, women_means, width, label='Women')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()


def autolabel(rects):
    """Attach a text label above each bar in *rects*, displaying its height."""
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom')


autolabel(rects1)
autolabel(rects2)

fig.tight_layout()

plt.show()

group bar plot with NO missing values

How can I plot the same bar plot with one missing value men_means list as follows.

labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35]
women_means = [25, 32, 34, 20, 25]

Here G5 is is absent in men_means

2 Answers 2

1

One can assign Zero values for men_means at G5 and do the plotting.

However it's not possible to know which index is missing in either of list. I suggest use of Dictionary to map the labels to specific values and then figure out which values it missing and assign it to Zero.

def fix_dict(data):
    labels = ['G1', 'G2', 'G3', 'G4', 'G5']
    for d in set(labels).difference(set(data.keys())):
        data[d] = 0
    return data
dict_men_means = {'G1':20, 'G2': 34, 'G3': 30, 'G4':35}
dict_women_means =  {'G1':25, 'G2': 32, 'G3': 34, 'G4':20, 'G5':25}
mean_means = [v for v in fix_dict(dict_men_means).values()]
women_means = [v for v in fix_dict(dict_women_means).values()]

Including this the code will become

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


labels = ['G1', 'G2', 'G3', 'G4', 'G5']
dict_men_means = {'G1':20, 'G2': 34, 'G3': 30, 'G4':35}
dict_women_means =  {'G1':25, 'G2': 32, 'G3': 34, 'G4':20, 'G5':25}
mean_means = [v for v in fix_dict(dict_men_means).values()]
women_means = [v for v in fix_dict(dict_women_means).values()]

x = np.arange(len(labels))  # the label locations
width = 0.35  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, men_means, width, label='Men')
rects2 = ax.bar(x + width/2, women_means, width, label='Women')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()


def autolabel(rects):
    """Attach a text label above each bar in *rects*, displaying its height."""
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom')


autolabel(rects1)
autolabel(rects2)

fig.tight_layout()

plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

0 is still shown on the top of the bar. Is there anyway we can avoid it to be shown on the top of the bar.
0

I tried it with if statement in autolabel function as follows.

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 0]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # the label locations
width = 0.35  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, men_means, width, label='Men')
rects2 = ax.bar(x + width/2, women_means, width, label='Women')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()


def autolabel(rects):
    """Attach a text label above each bar in *rects*, displaying its height."""
    for rect in rects:
        height = rect.get_height()
        
        if height!=0:
            
            ax.annotate('{}'.format(height),
                        xy=(rect.get_x() + rect.get_width() / 2, height),
                        xytext=(0, 3),  # 3 points vertical offset
                        textcoords="offset points",
                        ha='center', va='bottom')


autolabel(rects1)
autolabel(rects2)

fig.tight_layout()

plt.show()

enter image description here

1 Comment

I like your answer. However, since the value is missing, maybe it´s better to use [20, 34, 30, 35, float('nan')]. Then, instead of check "if height != 0", we can check "if math.isnan(height)"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.