matplotlib - Нет xlabel и xticks для двойных осей в фигурах подзаголовков

Я хочу сделать диаграммы 2x2 на подзаговоре. Затем для каждой фигуры я буду использовать две оси Y. Поэтому для каждой диаграммы я использовал метод twinx (). Проблема, как вы видите на рисунке, которым я поделился, заключается в том, что он не показывает xlabel и xticks для первой строки. Для второго ряда все нормально. Я указал на проблему красным шрифтом на рисунке («Нет xlabel и xticks !!!»).

Каждая диаграмма имеет свою ось x и ось y, и в этом нет разделения.

Я сильно изменил этот код и сузил список создателей проблем. Это потому, что я использую twinx () в верхних строках. Если я попытаюсь удалить вторичную ось y, все вернется в норму, и xlabel и ylabel для верхних строк будут отображаться правильно.

Не знаю, в чем проблема!

Это код, над которым я работаю.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from io import StringIO

s = StringIO(u"""     amount     price
A     40929   4066443
B     93904   9611272
C    188349  19360005
D    248438  24335536
E    205622  18888604
F    140173  12580900
G     76243   6751731
H     36859   3418329
I     29304   2758928
J     39768   3201269
K     30350   2867059""")

df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)

fig = plt.figure() 

ax_2 = fig.add_subplot(222, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([1, 3, 5, 7, 9])
ax_22.plot([1.0/x for x in [1, 3, 5, 7, 9]])
ax_2.set_xlabel("AX2 X Lablel")
ax_2.set_ylabel("AX2 Y Lablel")
ax_22.set_ylabel("AX2_Twin Y Lablel")


ax_2 = fig.add_subplot(223, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([100, 300, 500, 700, 900])
ax_22.plot([x*x for x in [100, 300, 500, 700, 900]])
ax_2.set_xlabel("AX3 X Lablel")
ax_2.set_ylabel("AX3 Y Lablel")
ax_22.set_ylabel("AX3_Twin Y Lablel")




ax_2 = fig.add_subplot(224, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX4 X Lablel")
ax_2.set_ylabel("AX4 Y Lablel")
ax_22.set_ylabel("AX4_Twin Y Lablel")






ax = fig.add_subplot(221, sharex=None, sharey=None) 
ax2 = ax.twinx() 
width = 0.4
df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1, sharex=False, sharey=False)
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0, sharex=False, sharey=False)

ax.set_xlabel("Alphabets")
ax.set_ylabel('Amount')
ax2.set_ylabel('Price')



plt.subplots_adjust(wspace=0.8, hspace=0.8)
plt.savefig("t1.png", dpi=300)
plt.show()

Он генерирует следующий рисунок:

выходной рисунок, полученный из приведенного выше кода на Python

ИЗМЕНИТЬ:

Спасибо за ответы. Однако моя проблема все еще существует при использовании Pandas для построения диаграмм. Я открыл новый вопрос. Пожалуйста, взгляните на это:

matplotlib - pandas - без xlabel и xticks для двухосных топоров на частичных рисунках


person Millad    schedule 04.02.2016    source источник


Ответы (2)


Код, который вы предоставили, похоже, дает желаемый результат.

тестовый запуск

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

Я бы рекомендовал переместить ax.set_xlabel перед twinx, например:

ax_2 = fig.add_subplot(222, sharex=None, sharey=None)
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX2 X Lablel")
ax_2.plot([1, 3, 5, 7, 9])

# Becomes...

ax_2 = fig.add_subplot(222, sharex=None, sharey=None)
ax_2.set_xlabel("AX2 X Lablel")
ax_2.plot([1, 3, 5, 7, 9])
ax_22 = ax_2.twinx()

ИЗМЕНИТЬ Я бы предложил вместо этого использовать gridspec. См. Рабочий пример ниже:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gspec
import numpy as np

fig = plt.figure()
gs = gspec.GridSpec(2, 2)
gs.update(hspace=0.7, wspace=0.7)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[1, 0])
ax3 = plt.subplot(gs[0, 1])
ax4 = plt.subplot(gs[1, 1])


x1 = np.linspace(1,10,10)

ax1.plot(x1, x1**2)
ax1.set_xlabel('ax1 x')
ax1_2 = ax1.twinx()
ax1_2.plot(x1, x1**3)
ax1_2.set_ylabel('ax1_2 y')
ax1.set_ylabel('ax1 y')

# To save time I left the other cells blank, but it should work fine.

plt.show()

Вышеупомянутое дает следующее:

пример сетки

person Oniow    schedule 04.02.2016
comment
Спасибо, Oniow. Даже с упомянутым вами изменением цифра не изменится! Я запускаю свой сценарий на своем Mac с 64-разрядной версией Ubuntu 14.04. Python: 2.7.11 (Скомпилировано с GCC 4.4.7) Matplotlib: 1.5.1 И я использую Anaconda 2.4.0 в качестве диспетчера пакетов для своих пакетов Python. - person Millad; 05.02.2016
comment
Вы каким-либо образом меняли мой код? Я спрашиваю об этом, потому что мне нужно создать диаграмму, и я хочу знать, ошибся я или нет. Отличается ли какая-либо из вышеупомянутых конфигураций системы от вашей? Спасибо за ваше время. - person Millad; 05.02.2016
comment
Привет, Миллад! Я смог создать этот график с помощью Python 3.4 и Matplotlib 1.5.0, а также с помощью Anaconda. Я не вносил изменений в ваш код, чтобы получить желаемый результат. Это может быть Python 3 против 2, но я в этом сомневаюсь. Какой интерфейс вы используете? Вы сохраняете цифру напрямую или выводите ее на что-то вроде консоли Ipython? - person Oniow; 05.02.2016
comment
В любом случае я бы предложил вместо этого использовать gridspec. Мне повезло больше, когда я столкнулся с подобными проблемами. См. Мой отредактированный ответ. - person Oniow; 05.02.2016
comment
Спасибо @Oniow. :) Я очень ценю это. gridspec, похоже, отлично работает на моем Python 2.7, что, как я думаю, является источником проблемы, поскольку вы упомянули, что используете Python 3. Я использую Python rawly, поэтому нет IPython, никаких других причуд: ). И я также наблюдаю такое поведение как в сохраненном мной файле, так и в окне вывода plt.show(). Я использовал ваш код, и он работал на моей машине для всех 4 диаграмм и для всех осей, которые я хотел :). Я принял ваш ответ как решение, но поскольку я недостаточно опытен с точки зрения stackoverflow, он может не отображаться как ответ. - person Millad; 05.02.2016

Вот как я подхожу к таким вопросам. Сначала попытайтесь изолировать проблему, сократив код до минимума. Например, этот код показывает ту же проблему:

fig = plt.figure()
fig.add_subplot(212)
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)

неправильный сюжет

Теперь мы видим две вещи:

  1. Если бы я допустил ошибку всего в 5 строках кода, ее было бы легко найти (по крайней мере, легче, чем с исходным кодом). Поскольку я не могу найти никаких ошибок, думаю, это ошибка в pandas или matplotlib. Из комментариев это может быть регрессия, представленная в matplotlib 1.5.1.

  2. В этом коде есть две необычные вещи:

    • The lower plot is created before the upper plot.
    • Фреймворк данных наносится на первичные оси после создания двойных осей.

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

fig = plt.figure() 
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)
fig.add_subplot(212)

правильный сюжет

Кажется, это работает, поэтому давайте попробуем то же самое с исходным кодом:

fig = plt.figure() 

ax = fig.add_subplot(221, sharex=None, sharey=None) 
ax2 = ax.twinx() 
width = 0.4
df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1, sharex=False, sharey=False)
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0, sharex=False, sharey=False)

ax_2 = fig.add_subplot(222, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([1, 3, 5, 7, 9])
ax_22.plot([1.0/x for x in [1, 3, 5, 7, 9]])
ax_2.set_xlabel("AX2 X Lablel")
ax_2.set_ylabel("AX2 Y Lablel")
ax_22.set_ylabel("AX2_Twin Y Lablel")

ax_2 = fig.add_subplot(223, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([100, 300, 500, 700, 900])
ax_22.plot([x*x for x in [100, 300, 500, 700, 900]])
ax_2.set_xlabel("AX3 X Lablel")
ax_2.set_ylabel("AX3 Y Lablel")
ax_22.set_ylabel("AX3_Twin Y Lablel")

ax_2 = fig.add_subplot(224, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX4 X Lablel")
ax_2.set_ylabel("AX4 Y Lablel")
ax_22.set_ylabel("AX4_Twin Y Lablel")

ax.set_xlabel("Alphabets")
ax.set_ylabel('Amount')
ax2.set_ylabel('Price')

plt.subplots_adjust(wspace=0.8, hspace=0.8)
plt.savefig("t1.png", dpi=300)
plt.show()

проблема решена

Итак, проблема решена (по крайней мере, для меня) с помощью обходного пути. Фактическое исправление было бы лучше, но идеальное - враг хорошего, и теперь подсюжеты создаются в более логичном порядке, что улучшает читаемость.

person Stop harming Monica    schedule 05.02.2016
comment
О Боже. Я смущен! Раньше это не работало, но сейчас работает нормально! Я думаю, это может быть связано с обновлением, которое я сделал для своих пакетов Python (matplotlib и pandas). Я также должен упомянуть, что причина, по которой я переместился вниз по коду, который генерирует мой верхний график, заключалась в том, что он не работал, и я подумал, может быть, это какая-то ошибка, что это изменение смещения вниз поможет с этим. Однако я очень ценю ваше время и усилия (я также принял ваш ответ). - person Millad; 05.02.2016
comment
Если вы определите ax3 = fig.add_subplot (212) и вызовете pd.Series (range (10)). Plot (ax = ax3), ось x оси x все равно исчезнет (?). - person Pat; 24.10.2017
comment
@Pat Я не знаю, куда вы хотите добавить этот код, но я рекомендую вам попробовать самостоятельно. - person Stop harming Monica; 24.10.2017