簡體   English   中英

matplotlib圖表 - 創建水平條形圖

[英]matplotlib chart - creating horizontal bar chart

我在以下片段中偶然發現,使用matplotlib創建水平條形圖:

import matplotlib
from pylab import *

val = 3+10*rand(5)    # the bar lengths
pos = arange(5)+.5    # the bar centers on the y axis
print pos
figure(1)
barh(pos,val, align='center')
yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim'))
xlabel('Performance')
title('horizontal bar chart using matplotlib')
grid(True)
show()

我想修改上面的腳本如下:

  1. 使繪制的條紋“不那么粗糙”(即降低繪制的水平條的高度)
  2. 將負數和正數繪制為同一圖上的水平條

幫助我做出上述修改的任何幫助(代碼片段或鏈接)都會非常有幫助。

順便說一句,如果我想制作堆疊的水平條(比如每個標簽有3個堆疊的水平條),我如何修改上面的代碼來繪制3個堆疊的水平條形圖?

[[編輯]]

有人可以發布兩個簡短的代碼片段,顯示如何:

  1. 在水平條的另一側打印標簽(例如,第一個隔離區中出現“負”條的標簽,第二個象限中出現“正”條的標簽

  2. 繪制多個(比如說2或3個)水平條(而不是一個)。 很好的例子是這里顯示前兩個圖像

import matplotlib
from pylab import *

val = 3-6*rand(5)    # the bar lengths        # changed your data slightly
pos = arange(5)+.5    # the bar centers on the y axis
print pos
figure(1)
barh(pos,val, align='center',height=0.1)    # notice the 'height' argument
yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim'))

gca().axvline(0,color='k',lw=3)   # poor man's zero level

xlabel('Performance')
title('horizontal bar chart using matplotlib')
grid(True)
show()

一般來說,我建議不要使用from pyplot import * 除非您處於交互模式,否則請使用面向對象的方法:

import matplotlib.pyplot as plt
from numpy.random import rand
from numpy import arange

val = 3-6*rand(5)    # the bar lengths
pos = arange(5)+.5    # the bar centers on the y axis
print pos

fig = plt.figure()
ax = fig.add_subplot(111)
ax.barh(pos,val, align='center',height=0.1)
ax.set_yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim'))

ax.axvline(0,color='k',lw=3)   # poor man's zero level

ax.set_xlabel('Performance')
ax.set_title('horizontal bar chart using matplotlib')
ax.grid(True)
plt.show()

matplotlib畫廊是各種情節的良好起點

正如振亞所說,你必須調整你的情節。

例如,下面是一個生成自定義水平條形圖的函數:

  • 輸入是數據,包含在字典中
  • 然后根據每個類別(人)中的度量(條形)數量以及要在每個類別之間放置的空間計算Y刻度的位置。
  • 最后,它繪制每個數據度量(如果您指定了它,則使用不同的顏色)

默認情況下,它會在右側繪制類別(人員)的名稱,但您當然可以更改它。

import numpy as np
import matplotlib.pyplot as plt

# creation of the data
name_list = ['day1', 'day2', 'day3', 'day4']
data = {name: 3+10*np.random.rand(5) for name in name_list}

colors_list = ['0.5', 'r', 'b', 'g'] #optional

def customize_barh(data, width_bar=1, width_space=0.5, colors=None):
    n_measure = len(data)                   #number of measure per people
    n_people = data[data.keys()[0]].size    # number of people

    #some calculation to determine the position of Y ticks labels
    total_space = n_people*(n_measure*width_bar)+(n_people-1)*width_space
    ind_space = n_measure*width_bar
    step = ind_space/2.
    pos = np.arange(step, total_space+width_space, ind_space+width_space)

    # create the figure and the axes to plot the data 
    fig = plt.figure(figsize=(8,6))
    ax = fig.add_axes([0.15, 0.15, 0.65, 0.7])

    # remove top and right spines and turn ticks off if no spine
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('right')    # ticks position on the right
    # postition of tick out
    ax.tick_params(axis='both', direction='out', width=3, length=6,
                   labelsize=24, pad=8)
    ax.spines['left'].set_linewidth(3)
    ax.spines['bottom'].set_linewidth(3)

    # plot the data
    for i,day in enumerate(data.keys()):
        if colors == None:
            ax.barh(pos-step+i*width_bar, data[day], width_bar, #facecolor='0.4',
                    edgecolor='k', linewidth=3)
        else:
            ax.barh(pos-step+i*width_bar, data[day], width_bar, facecolor=colors[i],
                    edgecolor='k', linewidth=3)


    ax.set_yticks(pos)
    # you may want to use the list of name as argument of the function to be more
    # flexible (if you have to add a people)
    ax.set_yticklabels(('Tom', 'Dick', 'Harry', 'Slim', 'Jim'))         
    ax.set_ylim((-width_space, total_space+width_space))
    ax.set_xlabel('Performance', size=26, labelpad=10)

customize_barh(data, colors=colors_list)
plt.savefig('perf.png')
plt.show()

產生: 這個

以下代碼片段是使用文本函數在左側為負值注釋文本標簽,在右側為陽性值注釋gcalmettes和Zhenya所示的示例。

from pylab import setp
import numpy as np
import matplotlib.pyplot as plt
import math

# creation of the data
name_list = ['day1', 'day2', 'day3', 'day4']
data = {name: 3+10*np.random.rand(5) for name in name_list}

for name in name_list:
  data[name][0] = data[name][0]*-1
  data[name][2] = data[name][2]*-1

colors_list = ['0.5', 'r', 'b', 'g'] #optional

def customize_barh(data, width_bar=1, width_space=0.5, colors=None):
    n_measure = len(data)                   #number of measure per people
    n_people = data[data.keys()[0]].size    # number of people

    #some calculation to determine the position of Y ticks labels
    total_space = n_people*(n_measure*width_bar)+(n_people-1)*width_space
    ind_space = n_measure*width_bar
    step = ind_space/2.
    pos = np.arange(step, total_space+width_space, ind_space+width_space)
    # create the figure and the axes to plot the data 
    fig = plt.figure(figsize=(8,6))
    ax = fig.add_axes([0.15, 0.15, 0.65, 0.7])

    # remove top and right spines and turn ticks off if no spine
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('default')    # ticks position on the right
    # postition of tick out
    ax.tick_params(axis='both', direction='out', width=3, length=6,
                   labelsize=24, pad=8)
    ax.spines['left'].set_linewidth(3)
    ax.spines['bottom'].set_linewidth(3)

    # plot the data
    for i,day in enumerate(data.keys()):
        if colors == None:
            ax.barh(pos-step+i*width_bar, data[day], width_bar, #facecolor='0.4',
                    edgecolor='k', linewidth=3)
        else:
            ax.barh(pos-step+i*width_bar, data[day], width_bar, facecolor=colors[i],
                    edgecolor='k', linewidth=3)


    ax.set_yticks(pos)
    # you may want to use the list of name as argument of the function to be more
    # flexible (if you have to add a people)
    setp(ax.get_yticklabels(), visible=False)         
    ax.set_ylim((-width_space, total_space+width_space))
    ax.set_xlabel('Performance', size=26, labelpad=10)
    labels_list = ['Tom', 'Dick', 'Harry', 'Slim','Jim']

    # creation of an array of positive/negative values (based on the values
    # of the data) that will be used as x values for adding text as side labels
    side_list = []
    for index in range(len(labels_list)):
        sum = 0
        for name in name_list:
            sum+= data[name][index]
        if math.copysign(1,sum) > 0:
            side_list.append(16)
        else:
            side_list.append(-21)
    for label in labels_list:
        plt.text(side_list[labels_list.index(label)], pos[labels_list.index(label)]-0.5, label,fontsize=26) 
customize_barh(data, colors=colors_list)
plt.savefig('perf.png')
plt.show()

它的工作原理是,給定人員的所有條形都需要為負或正,以便在正確的一側注釋文本。 要更改此行為,只需更改side_list的生成。

例如,如果您需要某個條形閾值來確定標簽的位置,則計算超過該閾值的數據值,而不是將給定名稱的值相加。

例如,對於很多的3個柱的閾值,for循環變為

for index in range(len(labels_list)):
        count = 0
            for name in name_list:
               if data[name][index] > 0:
                  count+= 1
            if count > 3:
              side_list.append(16)
            else:
              side_list.append(-21)

還需要更改side_list的生成以適應您的數據范圍,因為給出的示例使用指定范圍內的隨機數據。

例如,您需要調整side_list.append(16)side_list.append(-21)的標簽偏移量以適合您的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM