Создание несимметричных осей в matplotlib - PullRequest
0 голосов
/ 24 февраля 2020

Я пытаюсь создать график, представленный на изображении ниже. Я новичок в matplotlib, поэтому я не знаю, как создать ось без вставки некоторых данных. Например, если a имеет x и y и plot (x, y), будет создан график и ось тоже, но ось будет коррелирована с данными. В прикрепленном графике кривые представляют собой изолинии, поэтому корреляция данных не зависит точно от оси (зависит от функции, которую я описал в коде).

enter image description here

Как продолжить?

1 Ответ

1 голос
/ 24 февраля 2020

Вы можете использовать plt.xlim и plt.ylim, чтобы установить пределы для оси. С plt.grid вы можете контролировать отображение линий сетки. set_major_locator может установить положение для галочек и соответствующих линий сетки.

Положение для текста можно рассчитать, сначала найдя y на строке, которая соответствует x = 40. Если значение y будет слишком низким, мы можем вычислить значение x в строке, соответствующей y = -1500. Для поворота текста мы можем взять тангенс линии, который должен быть скорректирован соотношением сторон графика. Чтобы вращение оставалось действительным при изменении размера графика, можно установить фиксированное соотношение сторон.

Вот пример демонстрационного кода, с которого можно начать:

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import numpy as np

fig, ax = plt.subplots()

aspect = 1 / 300
ax.set_aspect(aspect)  # a fixed aspect ratio is needed so the text rotation stays equal to the line rotation
for iso in range(-5000, 16001, 1000):
    x1 = 25 + iso / 100
    x2 = -50
    y1 = -1000
    y2 = 7000 + iso
    plt.plot([x1, x2], [y1, y2], c='crimson', lw=2 if iso % 5000 == 0 else 0.5)
    if iso % 5000 == 0:
        # xt,yt:  x,y value for text; first try y position when x = 40; if too small find x position for y = -1500
        xt = 40
        yt = (y1 * (xt - x2) + y2 * (x1 - xt)) / (x1 - x2)
        if yt < y1:
            yt = -1500
            xt = (x1 * (yt - y2) + x2 * (y1 - yt)) / (y1 - y2)
        ax.text(xt, yt, iso if iso != 0 else "zero",
                {'ha': 'center', 'va': 'center', 'bbox': {'fc': 'lightgoldenrodyellow', 'pad': 2, 'alpha': 0.7}},
                rotation=np.arctan(aspect * (y1 - y2) / (x1 - x2)) / np.pi * 180)

ax.xaxis.set_major_locator(MultipleLocator(10))
ax.xaxis.set_minor_locator(MultipleLocator(5))
ax.xaxis.set_major_formatter(FormatStrFormatter('%d°C'))
ax.yaxis.set_major_locator(MultipleLocator(5000))
ax.yaxis.set_minor_locator(MultipleLocator(1000))
plt.grid(True, which='major', color='blue', linestyle='--', lw=0.5)
plt.grid(True, which='minor', color='blue', linestyle='--', lw=0.2)
plt.xlim(-50, 50)
plt.ylim(-5000, 20000)
plt.show()

result

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...