Как построить одну строку у-данных с двумя строками х-данных? - PullRequest
0 голосов
/ 25 марта 2020

Я хочу построить график с 1 набором y-данных, относящихся к 2 различным (но, конечно, связанным) наборам x-данных. Мои данные выглядят так:

x1          x2  y
1,84596E17  100 18,96342
2,27684E17  102 18,15215
2,80198E17  104 15,40415
3,44059E17  106 16,13399
4,21554E17  108 15,51298
5,15396E17  110 14,92131
6,28797E17  112 15,25483
7,65554E17  114 14,81549
9,30146E17  116 15,3397
1,12785E18  118 14,76562
1,36485E18  120 14,5095
1,64844E18  122 13,24967
1,98711E18  124 12,79743
2,39083E18  126 12,53556
2,87119E18  128 12,32063
3,44172E18  130 11,95121

Я хотел бы иметь логарифмически нормальный график (x1, y) в качестве основной информации. Для ориентации я хотел бы добавить вторую ось x (x2, y), которая соответствует графику (x1, y).

Есть ли способ позволить matplotlib напрямую вычислить масштабирование второго ось х не обязательно зная функциональную связь х1 и х2? Я также хотел бы избегать отображения одних и тех же y-данных дважды, а затем пытаться сопоставить границы осей, потому что это означало бы, что я должен знать функцию между x1 и x2.

Plot sketch

Я добавил небольшой набросок, который, надеюсь, прояснит мое намерение (извините за качество).

Спасибо, lepakk

Ответы [ 3 ]

1 голос
/ 25 марта 2020

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

Опираясь на данные другого ответа в этом В нити мы можем переопределить верхнюю ось x положение галочки и метку, чтобы сказать, что мы хотим. ВНИМАНИЕ: это отделяет значение данных от метки, делая его крайне ненадежным и подверженным ошибкам. Я обычно рассматриваю переопределение меток тиков как хак, и я не одобряю этот паттерн, когда занимаюсь наукой, разработкой, исследованием данных или даже при подготовке пояснительного рисунка. Но здесь мы, так что, пожалуйста, будьте осторожны ...

import matplotlib.pyplot as plt
x1 = [184596e17, 227684e17, 280198e17, 344059e17, 421554e17, 515396e17]
x2 = [100, 102, 104, 106, 108, 110]
y = [1896342, 1815215, 1540415, 1613399, 1551298, 1492131]

fig=plt.figure()
ax=fig.add_subplot(111, label="1")

ax.plot(x1, y, color="C0")
ax.set_xlabel("x label 1", color="C0")
ax.set_ylabel("y label 1")

ax2=ax.twiny()
ax2.set_xticks(x1)
ax2.set_xticklabels(x2)
ax2.plot(x1, y, color="C2", alpha=0)
ax2.xaxis.tick_top()
ax2.set_xlabel('x label 2', color="C1") 
ax2.tick_params(axis='x', colors="C1")

enter image description here

Теперь отметка на вторичной оси x совпадает с точкой данных и отображает его коррелирующее значение в другом пространстве «оси» в качестве метки галочки. Мне пришлось построить невидимый ряд, чтобы две шкалы по оси X точно совпали (вы также можете переопределить это, установив свои собственные значения xlim). Этот подход фактически эквивалентен добавлению аннотации к каждой точке данных, но немного чище.

Редактировать:

Не забывайте, что если у вас гораздо больше точек данных, чем пронумеровано желаемых отметок, вы можете переходить по позициям и меткам, чтобы получать каждые 2, 3 или 10 или 10 тиков положение и метка.

Для заметок на шаре:

stride=2
ax2.set_xticks(x1[::stride])
ax2.set_xticklabels(x2[::stride])

1 голос
/ 26 марта 2020

Если в случае, если вторичная ось x будет иметь линейную шкалу, соответствие можно принудительно установить, установив для xlims как соответствующее первое, так и последнее значения.

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

Обратите внимание, что главная ось x имеет только один основной тик и множество второстепенных тиков. При желании эти мелкие галочки могут также получить метку, используя set_minor_formatter(ticker.ScalarFormatter()).

from matplotlib import pyplot as plt
from matplotlib import ticker
import numpy as np

data = np.array([[1.84596E17, 100, 18.96342],
                 [2.27684E17, 102, 18.15215],
                 [2.80198E17, 104, 15.40415],
                 [3.44059E17, 106, 16.13399],
                 [4.21554E17, 108, 15.51298],
                 [5.15396E17, 110, 14.92131],
                 [6.28797E17, 112, 15.25483],
                 [7.65554E17, 114, 14.81549],
                 [9.30146E17, 116, 15.3397],
                 [1.12785E18, 118, 14.76562],
                 [1.36485E18, 120, 14.5095],
                 [1.64844E18, 122, 13.24967],
                 [1.98711E18, 124, 12.79743],
                 [2.39083E18, 126, 12.53556],
                 [2.87119E18, 128, 12.32063],
                 [3.44172E18, 130, 11.95121]])
x1 = data[:,0]
x2 = data[:,1].astype(int) # change to integer, so they get displayed as such
y = data[:,2]

fig, ax = plt.subplots()

ax.plot(x1, y, 'or-')
ax.set_xscale('log')
ax.set_xlabel('x1 (log scale)')
# ax.set_xlim(x1[0], x1[-1]) # optionally set tighter xlims
ax.xaxis.set_minor_formatter(ticker.ScalarFormatter()) # this shows the minor tick labels

ax2 = ax.twiny()
ax2.set_xlabel('x2')
ax2.set_xlim(ax.get_xlim()) # exactly the same limits for both axes
ax2.set_xscale('log')
ax2.set_xticks(x1) # set the tick positions via x1, but the labels via x2
ax2.set_xticklabels(x2)
ax2.xaxis.set_minor_locator(ticker.NullLocator()) # remove the old minor ticks
ax2.grid(True, axis='x', ls=':')

plt.tight_layout()
plt.show()

resulting plot

0 голосов
/ 25 марта 2020

Используя два (или более) графиков на одном графике с разными масштабами по оси X и по оси Y в python, в качестве ссылки ваш код будет выглядеть так:

import matplotlib.pyplot as plt

x1 = [184596e17, 227684e17,280198e17, 344059e17, 421554e17, 515396e17]
x2 = [100, 102, 104, 106, 108, 110]
y = [1896342, 1815215, 1540415, 1613399, 1551298, 1492131]

fig=plt.figure()
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)

ax.plot(x1, y, color="C0")
ax.set_xlabel("x label 1", color="C0")
ax.set_ylabel("y label 1", color="C0")

ax2.plot(x2, y, color="C1")
ax2.xaxis.tick_top()
ax2.set_xlabel('x label 2', color="C1") 
ax2.xaxis.set_label_position('top') 
ax2.tick_params(axis='x', colors="C1")


plt.savefig('stackoverflow.png', bbox_inches='tight')
plt.show()

и соответствующий вывод будет это изображение (принимая только 6 значений). enter image description here

Дайте мне знать, если у вас есть какие-либо вопросы :)

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