簡體   English   中英

如何在matplotlib中調整自動標記功能,使其正確顯示負值?

[英]How can I adapt the autolabel function in matplotlib so that it displays negative values correctly?

在過去的幾天里,我一直在使用Python,並且發現了很多關於標簽的好資源 ,但是我沒有正確顯示負值。 因為autolabel()函數采用條形的高度,這似乎總是一個正值,所以標簽在圖形中向上顯示,當然不會顯示為負值。 我可以以某種方式獲取構成這些條形的值,或者如何將這些標簽放在它們所屬的位置並將其顯示為負值?

import pandas as pd
import matplotlib.pyplot as plt
from builtins import list
import matplotlib
matplotlib.style.use('ggplot')
import numpy as np

n_groups = 2

# create plot
fig, ax = plt.subplots()
fig.canvas.set_window_title('Mindestlohn Bundesweit')
index = np.arange(n_groups)
bar_width = 0.20
opacity = 0.8

list_reallohn_week_vollzeit = [-8.159698443426123, 11.395025597733763]
list_reallohn_week_teilzeit = [-1.048913873322391, 28.99318154295449]
list_reallohn_week_mini = [-7.552596893170488, 7.959096278017519]


rects1 = plt.bar(index + 0.00, list_reallohn_week_vollzeit, bar_width,
             alpha=opacity,
             color='b',
             label='Vollzeit')
rects2 = plt.bar(index + bar_width, list_reallohn_week_teilzeit, bar_width,
             alpha=opacity,
             color='g',
             label='Teilzeit')
rects3 = plt.bar(index + bar_width * 2,list_reallohn_week_mini, bar_width,
             alpha = opacity,
             color='c',
             label='Mini Job')

label_week_lists = ('2014 vor MdL', '2015 Nicht MdL berechtigt', '2015 mit MdL')

plt.ylabel('EUR')
plt.title('Reallöhne pro Woche')
plt.xticks(index + bar_width, label_week_lists)
plt.legend(bbox_to_anchor=(1, 1),
       bbox_transform=plt.gcf().transFigure)

def autolabel(rects, ax):
# Get y-axis height to calculate label position from.
    (y_bottom, y_top) = ax.get_ylim()
    y_height = y_top - y_bottom

    for rect in rects:
        height = rect.get_height()
        # Fraction of axis height taken up by this rectangle
        p_height = (height / y_height)
        # If we can fit the label above the column, do that;
        # otherwise, put it inside the column.
        if p_height > 0.95: # arbitrary; 95% looked good to me.
            label_position = height - (y_height * 0.05)
        else:
            label_position = height + (y_height * 0.01)

        ax.text(rect.get_x() + rect.get_width() / 2., label_position,
            '%d' % int(height),
            ha='center', va='bottom')

autolabel(rects1, ax)
autolabel(rects2, ax)
autolabel(rects3, ax)

plt.show()

在此輸入圖像描述

如果你打印rect.get_height()值,你會得到類似的東西:

-8.159698443426123
11.395025597733763
-1.048913873322391
28.99318154295449
-7.552596893170488
7.959096278017519

因此,條形的高度可能是負的。

要標記負條,請修改auto標簽中的if語句,如下所示:

if p_height > 0.95: # arbitrary; 95% looked good to me.
    label_position = height - (y_height * 0.05) if (height > 0) else height + (y_height * 0.05) 
else:
    label_position = height + (y_height * 0.01) if (height > 0) else height - (y_height * 0.05) 

您必須手動調整else分支(0.05)中的系數,因為下面標簽的位置取決於標簽的字體大小。 (正條的標簽位置不受字體大小的影響,因為標簽位於條形圖上方)。

我的字體設置結局:

在此輸入圖像描述

mathplotlib在該部門沒有很好的文檔記錄。 嘗試使用dir()函數來顯示您正在處理的容器上的可用選項。 我發現有一個.get_y()函數在這種情況下返回負數

請嘗試使用此代碼

import pandas as pd
import matplotlib.pyplot as plt
from builtins import list
import matplotlib
matplotlib.style.use('ggplot')
import numpy as np

n_groups = 2

# create plot
fig, ax = plt.subplots()
fig.canvas.set_window_title('Mindestlohn Bundesweit')

index = np.arange(n_groups)
bar_width = 0.20
opacity = 0.8

list_reallohn_week_vollzeit = [-8.159698443426123, 11.395025597733763]
list_reallohn_week_teilzeit = [-1.048913873322391, 28.99318154295449]
list_reallohn_week_mini = [-7.552596893170488, 7.959096278017519]


rects1 = plt.bar(index + 0.00, list_reallohn_week_vollzeit, bar_width,
             alpha=opacity,
             color='b',
             label='Vollzeit')
rects2 = plt.bar(index + bar_width, list_reallohn_week_teilzeit, bar_width,
             alpha=opacity,
             color='g',
             label='Teilzeit')
rects3 = plt.bar(index + bar_width * 2,list_reallohn_week_mini, bar_width,
             alpha = opacity,
             color='c',
             label='Mini Job')

label_week_lists = ('2015 Nicht MdL berechtigt', '2015 mit MdL')

plt.ylabel('EUR')
plt.title('Reallöhne pro Woche')
plt.xticks(index + bar_width, label_week_lists)
plt.legend(bbox_to_anchor=(1, 1),
       bbox_transform=plt.gcf().transFigure)

def autolabel(rects, ax):
    # Get y-axis height to calculate label position from.
    (y_bottom, y_top) = ax.get_ylim()
    y_height = y_top - y_bottom

    for rect in rects:
    # print(dir(rect))

    height = 0
    if rect.get_y() < 0:
        height = rect.get_y()
    else:
        height = rect.get_height()

    print(rect.get_height())
    print( str(rect.get_y()) )

    # Fraction of axis height taken up by this rectangle
    p_height = (height / y_height)
    # If we can fit the label above the column, do that;
    # otherwise, put it inside the column.
    if p_height > 0.95:  # arbitrary; 95% looked good to me.
        label_position = height - (y_height * 0.05)
    else:
        label_position = height + (y_height * 0.01)

    ax.text(rect.get_x() + rect.get_width() / 2., label_position,
            '%d' % int(height),
            ha='center', va='bottom')

autolabel(rects1, ax)
autolabel(rects2, ax)
autolabel(rects3, ax)

plt.show()

暫無
暫無

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

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