Як додати другу вісь х у matplotlib


78

У мене дуже просте запитання. Мені потрібно мати другу вісь х на моїй ділянці, і я хочу, щоб ця вісь мала певну кількість тиків, які відповідають певному положенню першої осі.

Спробуємо на прикладі. Тут я будую графік маси темної речовини як функції коефіцієнта розширення, визначеного як 1 / (1 + z), який становить від 0 до 1.

semilogy(1/(1+z),mass_acc_massive,'-',label='DM')
xlim(0,1)
ylim(1e8,5e12)

Я хотів би мати іншу вісь x у верхній частині моєї ділянки, показуючи відповідну z для деяких значень коефіцієнта розширення. Це можливо? Якщо так, то як я можу отримати xtics ax


Функції, якими ви користуєтесь, не вбудовані в python - я припускаю, ви говорите про matplotlib ? Якщо так, запитання Як побудувати кілька осей x або y у matplotlib? здається, це охоплює.
Джеймс

Відповіді:


116

Я беру підказку з коментарів у відповіді @ Dhara, схоже, ви хочете встановити список new_tick_locationsза функцією від старої осі х до нової осі х. Нижче tick_functionнаведений масив точок Numpy, відображено їх до нового значення та форматовано:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

X = np.linspace(0,1,1000)
Y = np.cos(X*20)

ax1.plot(X,Y)
ax1.set_xlabel(r"Original x-axis: $X$")

new_tick_locations = np.array([.2, .5, .9])

def tick_function(X):
    V = 1/(1+X)
    return ["%.3f" % z for z in V]

ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(new_tick_locations))
ax2.set_xlabel(r"Modified x-axis: $1/(1+X)$")
plt.show()

введіть тут опис зображення


2
Якщо ви хочете додати заголовок , а також, побачити це питання: stackoverflow.com/questions/12750355 / ...
szmoore

@Hooked, будь-яка ідея, чи можливо це зробити за допомогою однієї з шкал у масштабі журналу?
тіаго,

2
@tiago Я не можу зараз це перевірити, але ax.set_yscale('log')працює?
Підключений

5
Цей приклад працює "випадково", оскільки xlims становлять від 0 до 1 (за замовчуванням). Щоб зробити цю роботу для довільних меж, потрібно також переконатися, що межі двох осей збігаються з чимось, як ax2.set_xlim(ax1.get_xlim())інакше, як Xдля верхньої, так і Xдля нижньої буде відрізнятися.
mforbes

Matplotlib реалізував власний спосіб додавання вторинної осі. Подивіться їх приклад тут: matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/…
Стефано,

27

Ви можете використовувати Twiny для створення 2 шкал по осі х. Наприклад:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

a = np.cos(2*np.pi*np.linspace(0, 1, 60.))

ax1.plot(range(60), a)
ax2.plot(range(100), np.ones(100)) # Create a dummy plot
ax2.cla()
plt.show()

Посилання: http://matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales

Вихід: введіть тут опис зображення


Вибачте, але це не те, про що я просив. Мені не потрібно будувати графік для функцій на одному графіку з різною віссю. Мені просто потрібно мати другу вісь х, у верхній частині моєї ділянки, позначену відповідно до якогось особливого положення на першій осі х.
Брайан

Потім просто додайте фіктивну 2-ю вісь із потрібним діапазоном та очистіть його. Дивіться мою відредаговану відповідь
Дара,

Вибачте, але ваш код не працює. Я скопіював і вставив його, а потім друга вісь х накладається на першу.
Брайан

Доданий результат, це не те, що ви отримуєте / хочете?
Дара,

Не зовсім. Беручи ваш приклад як посилання, я хотів би на другій осі х наступні наступні тики: (7,8,99), що відповідають положенню осі х 10, 30, 40. Чи можливо це якимось чином?
Брайан

12

Якщо ви хочете, щоб ваша верхня вісь була функцією значень нижньої осі:

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots()

ax1 = fig.add_subplot(111)

ax1.plot(range(5), range(5))

ax1.grid(True)

ax2 = ax1.twiny()
ax1Xs = ax1.get_xticks()

ax2Xs = []
for X in ax1Xs:
    ax2Xs.append(X * 2)

ax2.set_xticks(ax1Xs)
ax2.set_xbound(ax1.get_xbound())
ax2.set_xticklabels(ax2Xs)

title = ax1.set_title("Upper x-axis ticks are lower x-axis ticks doubled!")
title.set_y(1.1)
fig.subplots_adjust(top=0.85)

fig.savefig("1.png")

Дає:

введіть тут опис зображення


11

Відповідаючи на ваше запитання у коментарях до відповіді Дхари : " Я хотів би на другій осі х таких тиків: (7,8,99), що відповідають положенню осі х 10, 30, 40. Чи можливо це якимось чином? " Так , Це є.

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)

a = np.cos(2*np.pi*np.linspace(0, 1, 60.))
ax1.plot(range(60), a)

ax1.set_xlim(0, 60)
ax1.set_xlabel("x")
ax1.set_ylabel("y")

ax2 = ax1.twiny()
ax2.set_xlabel("x-transformed")
ax2.set_xlim(0, 60)
ax2.set_xticks([10, 30, 40])
ax2.set_xticklabels(['7','8','99'])

plt.show()

Ви отримаєте: введіть тут опис зображення


4

Починаючи з matplotlib 3.1, ви можете використовувати ax.secondary_xaxis

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(1,13, num=301)
y = (np.sin(x)+1.01)*3000

# Define function and its inverse
f = lambda x: 1/(1+x)
g = lambda x: 1/x-1

fig, ax = plt.subplots()
ax.semilogy(x, y, label='DM')

ax2 = ax.secondary_xaxis("top", functions=(f,g))

ax2.set_xlabel("1/(x+1)")
ax.set_xlabel("x")
plt.show()


2

Я змушений розмістити це як відповідь замість коментаря через низьку репутацію. У мене була подібна проблема з Маттео. Різниця полягає в тому, що у мене не було карти від моєї першої осі х до моєї другої осі х, лише самі значення х. Тому я хотів встановити дані на мою другу вісь х безпосередньо, а не галочки, однак, немає axes.set_xdata. Я зміг використати відповідь Дари, щоб зробити це зі зміною:

ax2.lines = []

замість використання:

ax2.cla()

Під час використання також очистив мою ділянку від ax1.


3
Це було б кращою відповіддю, якби ви надали приклад коду, а не просто зміни з відповіді Дхари.
Бенджамін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.