2017-08-10 58 views
0

我從Matplotlib這一形象: enter image description here的Python/Matplotlib - 查找一組棒的最高值

我想(圖cat i with i in [1-10])寫爲每個類別的最高值和其對應的傳奇在圖表上。 下面你可以找到直觀我想實現什麼: enter image description here

的東西是事實,我不知道這是否是可能的,因爲從matplotlib繪製的方式。

基本上,這是代碼的繪製多條部分:

# create plot 
fig, ax = plt.subplots(figsize = (9,9)) 
index = np.arange(len_category) 
if multiple: 
    bar_width = 0.3 
else : 
    bar_width = 1.5 
opacity = 1.0 
#test_array contains test1 and test2 
cmap = get_cmap(len(test_array)) 

for i in range(len(test_array)): 
     count = count + 1 
     current_label = test_array[i] 
     rects = plt.bar(index-0.2+bar_width*i, score_array[i], bar_width, alpha=opacity, color=np.random.rand(3,1),label=current_label) 

plt.xlabel('Categories') 
plt.ylabel('Scores') 
plt.title('Scores by Categories') 
plt.xticks(index + bar_width, categories_array) 
plt.legend()   

plt.tight_layout() 
plt.show() 

,這是我爲了做我想達到什麼樣的補充部分。但它會搜索圖形中所有條的最大值。例如,test1的最大值將在cat10中,而test2的最大值將是cat2。相反,我希望每個類別的最大值爲

for i in range(len(test_array)): 
     count = count + 1 
     current_label = test_array[i] 
     rects = plt.bar(index-0.2+bar_width*i, score_array[i], bar_width,alpha=opacity,color=np.random.rand(3,1),label=current_label) 

     max_score_current = max(score_array[i]) 
     list_rect = list() 
     max_height = 0 
     #The id of the rectangle who get the highest score 
     max_idx = 0 

     for idx,rect in enumerate(rects): 
      list_rect.append(rect) 
      height = rect.get_height() 
      if height > max_height: 
       max_height = height 
       max_idx = idx 
      highest_rect = list_rect[max_idx] 
      plt.text(highest_rect.get_x() + highest_rect.get_width()/2.0, max_height, str(test_array[i]),color='blue', fontweight='bold') 
     del list_rect[:] 

你知道我該如何做到這一點嗎?

謝謝

回答

2

通常最好保持數據生成和可視化分離。而不是循環通過酒吧本身,只需在繪圖之前獲取必要的數據。這使一切變得更加簡單。

因此,首先創建一個使用的標籤列表,然後在位置上循環以註釋。在下面的代碼中,標籤是通過將字段數組的argmax映射到測試集而創建的。

import numpy as np 
import matplotlib.pyplot as plt 

test1 = [6,4,5,8,3] 
test2 = [4,5,3,4,6] 

labeldic = {0:"test1", 1:"test2"} 

a = np.c_[test1,test2] 
maxi = np.max(a, axis=1) 
l = ["{} {}".format(i,labeldic[j]) for i,j in zip(maxi, np.argmax(a, axis=1))] 

for i in range(a.shape[1]): 
    plt.bar(np.arange(a.shape[0])+(i-1)*0.3, a[:,i], width=0.3, align="edge", 
      label = labeldic[i]) 

for i in range(a.shape[0]): 
    plt.annotate(l[i], xy=(i,maxi[i]), xytext=(0,10), 
       textcoords="offset points", ha="center") 
plt.margins(y=0.2) 
plt.legend() 
plt.show() 

enter image description here

+1

看着你的解決方案,我終於明白OP的想要什麼...... –

+0

@Thomas Yep,你是對的,這個問題並不完全清楚;我主要關注期望結果的「視覺」描述,而不是文本。 – ImportanceOfBeingErnest

+0

完美!它以這種方式運作良好!我明白你的意思了!非常感謝你。 – lilouch

2

從你的問題是不完全清楚你想達到什麼樣的,但假設你想在上面巴印刷的一組各條的相對高度,這裏是一個辦法實現這一目標:

from matplotlib import pyplot as plt 
import numpy as np 

score_array = np.random.rand(2,10) 
index = np.arange(score_array.shape[1]) 
test_array=['test1','test2'] 


opacity = 1 
bar_width = 0.25 

for i,label in enumerate(test_array): 
    rects = plt.bar(index-0.2+bar_width*i, score_array[i], bar_width,alpha=opacity,label=label) 
    heights = [r.get_height() for r in rects] 
    print(heights) 
    rel_heights = [h/max(heights) for h in heights] 
    idx = heights.index(max(heights)) 

    for i,(r,h, rh) in enumerate(zip(rects, heights, rel_heights)): 
     plt.text(r.get_x() + r.get_width()/2.0, h, '{:.2}'.format(rh), color='b', fontweight ='bold', ha='center') 

plt.show() 

結果看起來是這樣的:

enter image description here

+0

謝謝你的幫助!這不是我正在尋找的東西(一個人剛剛發佈了一個解決方案),但它非常有幫助。所以謝謝。 – lilouch