Сгруппированная гистограмма с настроенным индексом DateTime с использованием панд и Matplotlib - PullRequest
0 голосов
/ 10 октября 2019

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

Я предположил, что pandas мог бы легко справиться с этим, используя:

import pandas as pd
import matplotlib.pylab as plt
import matplotlib.dates as mdates

testdata = pd.DataFrame({"A": [1, 2, 3]
                       ,"B": [2, 3, 1]
                       , "C": [2, 3, 1]}  
                       ,index=pd.to_datetime(pd.DatetimeIndex(
                            data=["2019-03-02", "2019-04-01","2019-05-01"])))
ax = testdata.plot.bar()

Это создает сюжет, который я хочу, я просто хотел бы изменить дату на что-то более простое, например март 2019 г. , Апрель 2019 года, май 2019 года. grouped Bar charts but the x-Axis labels suck

Я предполагал, что использование пользовательского форматера даты будет работать, поэтому я попытался

ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))

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

fig, ax = plt.subplots()
width = 0.8
ax.bar(testdata.index, testdata["A"]) 
ax.bar(testdata.index, testdata["B"])
ax.bar(testdata.index, testdata["C"])
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))
plt.show()

Теперь представление даты соответствует ожидаемому (хотя пробел может быть уменьшен), но данные перекрываются, что не помогает. enter image description here

Определение ширины и вычитание ее из значений x (как обычно предлагается) не поможет из-за использования DateTime-Index, который я использую. Я получаю сообщение об ошибке, что вычитание DatetimeIndes и float не поддерживается.

fig, ax = plt.subplots()
width = 0.8
ax.bar(testdata.index-width, testdata["A"]) 
ax.bar(testdata.index, testdata["B"])
ax.bar(testdata.index+width, testdata["C"])
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))
plt.show()

Так что теперь у меня заканчиваются идеи и надежда на ввод

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Причина ax.xaxis.set_major_locator(mdates.MonthLocator()) терпит неудачу, потому что под капотом pandas строит столбцы против range(len(df)), затем переименовывает галочки соответственно.

Вы можете получить xticklabels после построения графика и переформатировать его:

ax = testdata.plot.bar()

ticks = [tick.get_text() for tick in ax.get_xticklabels()]
ticks = pd.to_datetime(ticks).strftime('%b %Y')
ax.set_xticklabels(ticks)

, что дает тот же результат, что и ImpotanceOfBeingErnest's:

enter image description here

Другой, возможно, лучший способ - это сдвигать столбцы каждого столбца. Это работает лучше, когда у вас много столбцов и вы хотите уменьшить количество xticks.

fig, ax = plt.subplots()

# define the shift
shift = pd.to_timedelta('1D')

# modify the base of each columns, can do with a for loop
ax.bar(testdata.index + shift, testdata["A"]) 
ax.bar(testdata.index, testdata["B"])
ax.bar(testdata.index - shift, testdata["C"])
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))
plt.show()

Вывод:

enter image description here

1 голос
/ 11 октября 2019

Pandas barplots являются категоричными. Так что, может быть, вы обдумываете это и просто хотите использовать строку, которую хотите видеть в качестве метки категории на оси в качестве индекса?

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"A": [1, 2, 3]
                       ,"B": [2, 3, 1]
                       , "C": [2, 3, 1]}  
                       ,index=pd.to_datetime(pd.DatetimeIndex(
                            data=["2019-03-02", "2019-04-01","2019-05-01"])))

df.index = [d.strftime("%b %Y") for d in df.index]
ax = df.plot.bar()
plt.show()

enter image description here

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