I am generating a barplot with many elements. As shown below, the plot generated is not very easy to read. How can I adjust it to make it look better and move the columns a bit further?
Here is the code.
import numpy as np
import matplotlib.pyplot as plt
def barchart(Gbar, Vbar, Wbar, Rbar, Dbar, Nebar, Tbar, Abar):
N = 10
G = Gbar
ind = np.arange(N) # the x locations for the groups
width = 0.12 # the width of the bars
fig, ax = plt.subplots()
rects1 = ax.bar(ind, G, width, color='b')
V = Vbar
rects2 = ax.bar(ind + width, V, width, color='g')
W = Wbar
rects3 = ax.bar(ind + width*2, W, width, color='y')
R = Rbar
rects4 = ax.bar(ind + width*3, R, width, color='r')
D = Dbar
rects5 = ax.bar(ind + width * 4, D, width, color='orange')
N = Nebar
rects6 = ax.bar(ind + width * 5, N, width, color='black')
T = Tbar
rects7 = ax.bar(ind + width * 6, T, width, color='purple')
Ab = Abar
rects8 = ax.bar(ind + width * 7, Ab, width, color='cyan')
# add some text for labels, title and axes ticks
ax.set_ylabel('Char edit distance')
ax.set_xticks(ind + width/2)
ax.set_xticklabels(('A1', 'A2', 'A3', 'A4', 'A5', 'B1', 'B2',
'B3', 'B4', 'C1'))
ax.legend((rects1[0], rects2[0], rects3[0], rects4[0], rects5[0],rects6[0],rects7[0],rects8[0]),
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height), ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
autolabel(rects4)
autolabel(rects5)
autolabel(rects6)
autolabel(rects7)
autolabel(rects8)
plt.savefig('plot.png')
plt.show()
Note: the image attached is part of the entire image but should be more than enough to get an idea about my issue.
Reusing part of the code in the previous answer and implementing my suggestions the code would look like the following
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
Google = [10, 15, 32, 29, 13, 35, 2, 20, 27, 29]
Voicebase = [2, 16, 19, 30, 22, 30, 33, 4, 14, 18]
Watson = [7, 17, 14, 19, 28, 4, 4, 34, 9, 17]
Remeeting = [12, 21, 19, 35, 24, 6, 22, 31, 19, 14]
fig, ax = plt.subplots()
labels = ('A1', 'A2', 'A3', 'A4', 'A5','B1', 'B2', 'B3', 'B4', 'C1')
y_pos = np.arange(len(labels))*4
rects1 = ax.barh(y_pos + width, Google)
rects2 = ax.barh(y_pos + 2*width, Voicebase)
rects3 = ax.barh(y_pos + 3*width, Watson)
rects4 = ax.barh(y_pos + 4*width, Remeeting)
# add some text for labels, title and axes ticks
ax.set_yticks(y_pos+2)
ax.set_yticklabels(labels)
ax.set_xlabel('Some label')
ax.set_ylabel('Another label')
ax.legend((rects1[0], rects2[0], rects3[0], rects4[0]), ('Google', 'Voicebase','Watson', 'Remeeting'))
plt.show()
Which results in the following
This should provide a good starting point to keep improving the visualization of your plot. I explicitly removed the numbers as I find it too much information and makes the plot messy.
The fact that you have a lot of bars on your graph means that having the values there may have some overlapping no matter what you do. That being said, there are a few things that can improve the look. One would be to increase the figure size. The next would be to reduce the font size of your labels. Taking the code from your previous question and modifying it a bit:
Google = [10, 15, 32, 29, 13, 35, 2, 20, 27, 29]
Voicebase = [2, 16, 19, 30, 22, 30, 33, 4, 14, 18]
Watson = [7, 17, 14, 19, 28, 4, 4, 34, 9, 17]
Remeeting = [12, 21, 19, 35, 24, 6, 22, 31, 19, 14]
ind = np.arange(1,80,8)# the x locations for the groups
width = 0.9 # the width of the bars
fig, ax = plt.subplots(figsize=(14,6)) #increase figure size
rects1 = ax.bar(ind, Google, width, color='b')
rects2 = ax.bar(ind + width, Voicebase, width, color='g')
rects3 = ax.bar(ind + width*2, Watson, width, color='y')
rects4 = ax.bar(ind + width*3, Remeeting, width, color='r')
rects5 = ax.bar(ind + width*4, Google, width, color='orange')
rects6 = ax.bar(ind + width*5, Voicebase, width, color='black')
rects7 = ax.bar(ind + width*6, Watson, width, color='purple')
rects8 = ax.bar(ind + width*7, Remeeting, width, color='cyan')
# add some text for labels, title and axes ticks
ax.set_ylabel('Char edit distance')
ax.set_xticks(ind + width/2 )
ax.set_xticklabels(('A1', 'A2', 'A3', 'A4', 'A5','B1', 'B2', 'B3', 'B4', 'C1'))
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom',fontsize=8) # decrease label size
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
autolabel(rects4)
autolabel(rects5)
autolabel(rects6)
autolabel(rects7)
autolabel(rects8)
plt.subplots_adjust(left=0.08,right=0.95)
plt.show()
Gives the figure:
Edit
The legend documentation can be found here . The legend can be moved by using the loc=
argument in ax.legend()
. Setting a value of 1 will put the legend in the top right, 2 will be top left etc.
You can move the legend outside of your plot by using bbox_to_anchor()
. This will reduce the size of your bar chart and therefore might lead to more overlapping in the labels. You can also try reducing the fontsize of the legend to reduce the effect of this. Using
ax.legend((rects1[0], rects2[0], rects3[0], rects4[0], rects5[0], rects6[0], rects7[0], rects8[0]),
bbox_to_anchor=(1, 1),fontsize=8)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.