#python #matplotlib #plot
Вопрос:
TLDR: То, что я ищу, — это способ построить список временных меток в виде равноудаленных точек данных с mpl
определением того, какие метки показывать.
Если равноудаленное построение точек данных с метками времени возможно только путем преобразования меток времени в строки (и, таким образом, построения их в виде категориальной оси), мой вопрос также можно сформулировать так: как можно mpl
автоматически удалять метки с переполненной категориальной оси?
Подробные сведения:
У меня есть временные ряды с ежемесячными данными, которые я хотел бы отобразить в виде гистограммы. Моя проблема в том, что matplotlib.pyplot
эти данные автоматически отображаются на временной оси:
import matplotlib.pyplot as plt
import pandas as pd
fig, ax = plt.subplots(1, 1, )
s = pd.Series(range(3,7), pd.date_range('2021', freq='MS', periods=4))
ax.bar(s.index, s.values, 27) # width 27 days
ax.set_ylabel('income [Eur]')
Обычно это то, что я хочу, но с ежемесячными данными это выглядит странно, потому что февраль значительно короче. Чего я хочу, так это чтобы данные были нанесены на одинаковое расстояние. Есть ли способ заставить это сделать?
Важно отметить, что я хочу сохранить поведение, которое, например, отображается только вторая или третья метка, как только ось x становится слишком переполненной, без необходимости настраивать ее вручную.
То, что я пытался или не хочу делать:
- Я мог бы сделать промежутки между прутьями одинаковыми — изменив ширину прутьев. Однако я строю данные о доходах [Eur], что означает, что неравномерная ширина полосы вводит в заблуждение.
- Я мог бы превратить временные метки в строку, чтобы данные отображались категорически:
s = pd.Series(range(3,7), pd.date_range('2021', freq='MS', periods=4))
x = [f'{ts.year}-{ts.month:02}' for ts in s.index]
ax.bar(x, s.values, 0.9) # width now as fraction of spacing between datapoints
Однако это наводит mpl
на мысль, что каждая метка должна быть нанесена на график, который становится переполненным:
s = pd.Series(range(3,17), pd.date_range('2021', freq='MS', periods=14))
x = [f'{ts.year}-{ts.month:02}' for ts in s.index]
ax.bar(x, s.values, 0.9) # width now as fraction of spacing between datapoints
Комментарии:
1. Вы хотите преобразовать тип данных из пользовательского в тип категории?
2. Спасибо за ваш комментарий. Нет; если я это сделаю, каждая метка всегда будет отображаться. Я хотел бы преобразовать их в числовое значение, представленное пользовательской меткой, если возможно что-то подобное. Таким образом, как и в случае с любой другой числовой осью, используется интервал между метками, который соответствует доступному пространству.
Ответ №1:
Вы можете расставить свои категоричные галочки с MaxNLocator
помощью .
- Учитывая ваш более крупный образец серии с категориальными ярлыками:
s = pd.Series(range(3,17), pd.date_range('2021', freq='MS', periods=14)) x = [f'{ts.year}-{ts.month:02}' for ts in s.index] fig, ax = plt.subplots() ax.bar(x, s.values, 0.9) ax.set_ylabel('income [Eur]')
- Примените
MaxNLocator
с указанным количеством ячеек (или'auto'
):from matplotlib.ticker import MaxNLocator locator = MaxNLocator(nbins=5) # or nbins='auto' ax.xaxis.set_major_locator(locator)
Комментарии:
1. Спасибо за ответ @tdy, однако в этом решении по-прежнему используется ось времени. Месяцы распределены в соответствии с их продолжительностью, как видно, особенно в период с февраля по март. — Я ищу решение, которое распределяет месяцы равномерно (как я определил
x
), но также удаляет метки, если их слишком много, так как (в отличие от «нормальной» категориальной оси) можно вывести пропущенные значения.2. Я обновил вопрос, чтобы немного прояснить, что именно я ищу.
3. @ElRudi ах понял, тогда я полагаю, что вы ищете MaxNLocator (ответ обновлен)