Перекрытие в python plt.text, пакет корректировки_текста не работает, как это исправить?

У меня есть два объекта фрейма данных pandas с именами «freq» и ​​«freq1000», каждый из которых представляет собой вектор из 5 чисел. Я хочу нарисовать их на одном графике с plt.text на графике, чтобы показать значения y. 'freq' и 'freq1000' состоят из 'pr' и 'pr1000', оба из которых генерируются с помощью чрезвычайно длительных процедур. Чтобы избежать перекрытия plt.text, я перешел по ссылке Как исправить перекрытие аннотаций/текста и установил пакет Adjust_text. Однако это не сработало так, как я хотел, и на полученном графике все еще есть перекрытие фигур на графике, см. рисунок ниже:

Мой связанный импорт и коды включены ниже.

import pandas as pd
import matplotlib.pyplot as plt
from adjustText import adjust_text



freq = pd.DataFrame(np.average(pr, axis=0), index=pr.columns) 
freq1000 = pd.DataFrame(np.average(pr1000, axis=0), index=pr1000.columns)    
plt.plot(freq, label='n=500')
plt.plot(freq1000, label='n=1000')
plt.legend(loc='best')



plt.xlabel('x')
plt.ylabel('y')
plt.title('curve high vs low,gtype{}'.format(type_))
# plt.close()
texts=[]
for x, y in zip(freq.index, freq.values):
    texts.append(plt.text(x, y,'%.3f' % y))
adjust_text(texts, only_move = {'points':'y', 'texts':'xy'}, arrowprops=dict(arrowstyle = "->", color='r', lw=0.5))
texts=[]
for x, y in zip(freq1000.index, freq1000.values):
    texts.append(plt.text(x, y,'%.3f' % y))
adjust_text(texts, only_move = {'points':'y', 'texts':'y'}, arrowprops=dict(arrowstyle = "->", color='r', lw=0.5))

Как мне исправить коды, чтобы решить проблему перекрытия? Спасибо!

Пожалуйста, включите ваш импорт.

jared 26.04.2024 17:23

@джаред, спасибо! Буду редактировать и обновлять мой вопрос.

ExcitedSnail 26.04.2024 17:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это попытка сделать что-то с меньшим дублированием, но с некоторой настройкой, необходимой, если что-то часто меняется. ax.annotate выполняет большую часть работы, но есть некоторые дополнительные параметры для дополнительной настройки. Основная идея — сместить синие метки влево, а оранжевые — вправо.

Одна из оранжевых меток перекрывает линию. Вы можете принудительно отключить его вручную, если это необходимо для одноразового графика, но я не сделал этого, чтобы сделать ответ более обобщаемым и устойчивым к новым случаям.

from matplotlib import pyplot as plt

pr_x = [-1, -0.5, 0, 0.5, 1]
pr_y = [1, 0.683, 0.067, 0.5, 1]
color_pr = 'tab:blue'

pr1000_x = [-1, -0.5, 0, 0.5, 1]
pr1000_y = [1, 0.983, 0.05, 0.917, 1]
color_pr1000 = 'tab:orange'

f, ax = plt.subplots(figsize=(6, 3))
ax.plot(pr_x, pr_y, color=color_pr, marker='o', label='n=500')
ax.plot(pr1000_x, pr1000_y, color=color_pr1000, marker='o', label='n=1000')

ax.set(xlabel='x', ylabel='y', title='curve high vs low, gtype2')
ax.legend()

for x, y in zip(pr_x, pr_y):
    ax.annotate(
        f'{y:.3f}', (x, y),
        xytext=(-0.6, 0), textcoords='offset fontsize', #shift blue pts left
        horizontalalignment='right', verticalalignment='center',
        weight='bold', fontsize=8, color=color_pr,
    )
    
for x, y in zip(pr1000_x, pr1000_y):
    ax.annotate(
        f'{y:.3f}', (x, y),
        xytext=(0.6, 0.2), textcoords='offset fontsize', #shift orange pts up, right
        horizontalalignment='left', verticalalignment='bottom',
        weight='bold', fontsize=8, color=color_pr1000,
        # rotation=20
    )
    
ax.set_xlim(ax.get_xlim()[0] * 1.15, ax.get_xlim()[1]) #make x axis wider
ax.spines[['right', 'top']].set_visible(False)

Это альтернативный вариант, который имеет меньший потенциал дублирования. Для каждого графика есть визуальное руководство, но числа разделены на два графика.

Я думаю, что seabornFacetGrid могли бы сделать что-то подобное и с меньшим количеством кода, если бы вы были заинтересованы в дальнейшем изучении такого рода механизмов.

f, axs = plt.subplots(ncols=2, nrows=1, figsize=(7, 3), sharey=True, layout='tight')

pr_data = (pr_x, pr_y, 'n=500')
pr1000_data = (pr1000_x, pr1000_y, 'n=1000')

for ax in axs:
    fg_data = pr_data if ax==axs[0] else pr1000_data
    bg_data  = pr_data if ax==axs[1] else pr1000_data
    
    #Foreground data
    x, y, label = fg_data
    ax.plot(x, y, 'tab:purple', marker='o', markersize=7, linewidth=3, label=label)
    
    for x_i, y_i in zip(x, y):
        ax.annotate(
            f'{y_i:.3f}', (x_i, y_i), xytext=(1, 0.6), textcoords='offset fontsize',
            horizontalalignment='left', verticalalignment='top',
            color='midnightblue', weight='bold', size=8, rotation=0,
        )
    
    #Background data
    x, y, label = bg_data
    ax.plot(x, y, 'black', marker='o', markersize=6,
            linewidth=4.5, linestyle='-', alpha=0.12,
            label=label, zorder=0)
    
    ax.set_xlabel('x')
    ax.spines[['right', 'top']].set_visible(False)
    ax.set_title(label, color='rebeccapurple', weight='bold')
    # ax.legend()

    axs[0].set_ylabel('y')

Большое спасибо за два отличных решения, очень ценю их! Еще несколько дополнительных вопросов: во-первых, в вашем первом решении нет ли опечаток в кодах? Например, на первом графике, который вы показываете, везде 1 вместо pr_y, как это исправить? Кроме того, должно ли «для xy в zip(pr_x, pr_y)» быть «для x,y в zip(pr_x,pr_y)»?

ExcitedSnail 30.04.2024 04:54

С удовольствием @ExcitedSnail. Вы правы, в коде есть опечатки, которые я сейчас исправил.

MuhammedYunus 30.04.2024 10:08

Другие вопросы по теме

Похожие вопросы

Chatgpt API продолжает возвращать ошибку: 404 Не удалось получить ответ от API
Запускайте все утверждения PyTest даже при нескольких ошибках (нет возможности разделить тесты)
Код pyspark на блоках данных никогда не завершает выполнение и зависает между ними
Как использовать LifespanManager для тестирования обратного прокси-сервера в FastAPI (асинхронное тестирование)
Как заполнить входные данные PowerShell сценарием Python?
Деформация изображения с заданным набором точек
Как правильно запланировать и дождаться результата асинхронного кода из синхронного контекста в блокноте Jupyter?
Развертывание приложения Python в веб-приложении Azure из конвейера, не включая пакеты требований
Как настроить токенизатор spaCy так, чтобы он разделял число, за которым следует точка в конце строки, в немецкой модели
MyPy не любит кортежи, присвоенные переменным, а затем используемые в качестве аргументов типа