dataframe.plot.bar () не обрабатывает индексы периода как 'x' правильно - PullRequest
3 голосов
/ 10 марта 2020

Я обнаружил, что мне кажется, ошибка в интеграции между matplotlib и pandas.DataFrame, хотя, возможно, я ошибаюсь.

У меня есть период времени, когда я хочу построить столбчатые диаграммы с барами, представляющими квартальные периоды. Я хочу зафиксировать начальную и конечную дату оси, даже если мои данные не проходят полностью слева или справа от оси.

Мой график данных, который я строю, имеет периоды в качестве индекса. Я обнаружил, что хотя руководство (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.bar.html) указывает на то, что индекс принимается за x, мы видим, что ax.get_xticks() возвращает целые числа 0,1,2,.. как xticks, что означает, что я не могу легко предоставить новый максимум / мин для шкалы.

Далее, когда я пытаюсь установить диапазон через ax.set_xticks() или ax.set_xlim(), я получаю ошибку TypeError: Axis must have freq set to convert to Period.

Так что получается, что я) я не могу добавить тиковые диапазоны легко, поскольку я не могу установить x в качестве индекса; и ii) я не могу использовать серии периодов (или, по-видимому, DateTime) в качестве входных данных для функций оси, чтобы установить диапазон, так как для него требуется частота.

Я делаю это, потому что stacked=True является допустимым входным значением для py.DataFrame.plot.bar(), тогда как нет интегрированного способа построения стековых диаграмм с plt.plot() или plt.plot.bar().

Заметьте, я уже сделал это «в долгий путь», и проблема i) решена, что заставляет меня думать, что это ошибка. Я до сих пор не могу предоставить свой период индекса idx_dts для установки диапазона оси X.

Вот пример кода:

 # external modules
import pandas as pd

# create a dataframe with a long periodindex
asof = pd.datetime(2019, 12, 31)
report_freq = 'Q-NOV'
num_periods = 8

idx_dts = pd.date_range(end=asof,
                        freq=report_freq,
                        periods=num_periods,
                        name='periods')

idx_dts = idx_dts.to_period(report_freq)
idx_dts   # a period.PeriodIndex

# set a shorter dataframe not covering the full span of periods
df = pd.DataFrame({'a': (1,2,3,4), 'b': (6,7,8,9), 'c': (10,20,30,40)})
df.index = idx_dts[3:7]

# take a look at the dataframe
df

# plot as a stacked barchart
ax=df.plot.bar(stacked=True)

# notice ticks are array([0,1,2,3]) NOT the index of df as indicated
ax.get_xticks()

# labels have been taken from the index though
ax.get_xticklabels()[:]

# I want to set a wider periods axis corresponding toe idx_dts
# error: 'TypeError: Axis must have `freq` set to convert to Periods'
ax.set_xticks(idx_dts)
...