简体   繁体   中英

How can I adjust my plot to make it easier to read?

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)

Gives: 在此处输入图片说明

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM