Автоизменение размера текста над графиками matplotlib

from random import randint
import matplotlib.pyplot as plt
import math
 
def create_graphs(
    word: list,
    count: list,
    peer_id: int,
    xlabel: str,
    ylabel: str,
    title: str,
    resize: bool = False,
    flag_size: bool = False,
    turn: bool = True,
    limit: bool = False,
):
    """Функция возвращает attachment - график
 
   Аргументы:
   :param turn True если нужен текст повернуть
   :param resize: True если нужно изменить размер
   :param flag_size: True если нужен размер побольше
   :param word: список слов
   :param count: список чисел
   :param peer_id: id чата
   :param xlabel: надпись по оси x
   :param ylabel: надпись по оси y
   :param title: заголовок
   :param limit: True если нужно уменшить подпись
 
   Пример:
   create_graphs(word = word, count = count, peer_id = message_data.peer_id, xlabel = "Слова", ylabel = "Количество", title="Топ популярных слов в чате")
 
   :return: Attachment - график"""
    # если нужно уменьшить количество цифр
    if limit:
        # узнаем длину списка
        len_list = len(word)
 
        NUMBER_DATE = 8
        number_of_date = math.ceil(len_list/NUMBER_DATE)
 
    # так можно изменить размер фигуры
    #fig, ax = plt.subplots(1, figsize=(7, 4))
    fig, ax = plt.subplots(1)
    # рандомим
    def r():
        return randint(20, 220)
 
    # рандомно задаём генерацию цвета
    random_color = "#%02X%02X%02X" % (r(), r(), r())
    # отрисовываем сетку
    plt.grid()
    ax.set_axisbelow(True)
    # создаём график из слов и количества слов, также передаём рандомный цвет в формате HEX
    barplot = ax.bar(word, count, color=random_color, alpha=0.8)
    # Получаем один столбик из всех в переменной bar
    for bar in barplot:
        # координаты х
        x_value = float(bar.get_x() + bar.get_width() / 2)
        # координаты у
        y_value = float(bar.get_height())
        # получаем высоту графика
        yval = bar.get_height()
        # пишем над графиком цифру
        plt.text(x_value, y_value, int(yval), va="bottom", horizontalalignment="center")
    # делаем горизонтальный текст
    #if turn:
    fig.autofmt_xdate()
    plt.xlabel(xlabel)
    # если нужно уменьшить количество цифр
    if limit:
        # устанавливаем расстояние между графиками
        plt.xticks(word[::number_of_date])
    plt.ylabel(ylabel)
    plt.title(title)
    # сохраняем в памяти и загружаем в вк
    if resize:
        fig = plt.gcf()
        if flag_size:
            fig.set_size_inches(12, 12)
        else:
            fig.set_size_inches(6.5, 6.5)
        fig.savefig("test.png", format="png", dpi=150, bbox_inches='tight')
    else:
        plt.savefig("test.png", format="png", dpi=150, bbox_inches='tight')

Вызываю:

create_graphs(word=['23.05', '24.05', '25.05', '26.05', '27.05', '28.05', '29.05', '30.05', '31.05', '01.06', '02.06', '03.06', '04.06', '05.06', '06.06', '07.06', '08.06', '09.06', '12.06', '13.06', '15.06', '16.06', '17.06', '18.06', '21.06', '22.06', '23.06', '25.06', '26.06', '27.06', '28.06', '29.06', '30.06', '01.07', '03.07', '04.07', '05.07', '06.07', '07.07', '08.07', '09.07', '10.07', '11.07', '12.07', '13.07', '14.07', '15.07', '16.07', '17.07'],
                count=[28, 50, 61, 262, 117, 175, 35, 24, 10, 95, 24, 173, 58, 19, 24, 2, 3, 7, 16, 32, 55, 87, 2, 15, 26, 96, 26, 51, 6, 29, 44, 71, 2, 16, 101, 9, 35, 22, 30, 101, 68, 121, 18, 51, 33, 67, 111, 30, 6],
                peer_id=0,
                xlabel="",
                ylabel="",
                title="Статистика активности по сообщениям",
                turn=False,
                limit=True
            )

Однако, если данных много цифры выходят за график и это выглядит некрасиво, как быть? введите сюда описание изображения


Ответы (1 шт):

Автор решения: passant

Во-первых, ваш скрипт без изменения у меня, например, выглядит вполне пристойно введите сюда описание изображения

Во-вторых, можно, конечно менять размер шрифта, а можно и повернуть сами надписи над столбиками, например - вот так введите сюда описание изображения

Для этого просто заменяем строчку вывода значений на

 plt.text(x_value, y_value, int(yval), va="top", horizontalalignment="center", rotation=90)
→ Ссылка