Постройте столбчатую диаграмму (100%) для нескольких категорий на несколько дат в Python

#pandas #matplotlib #bar-chart #grouping

Вопрос:

У меня есть следующий начальный кадр данных:

Почтовый идентификатор Submission_Date Чутье
0 строка 1 01.12.2020 NaN
1 строка 2 03.12.2020 Обсуждение
2 строка 3 03.12.2020 Новости
3 строка 4 03.12.2020 Обсуждение
4 строка 5 06.12.2020 должное усердие
5 строка 6 07.12.2020 Обсуждение
6 строка 7 31.12.2020 Обсуждение
1 строка 8 01.01.2021 Слезы Хедж-фонда
  • Несколько дат с пропущенными датами между ними
  • Несколько категорий по датам

Я сгруппировал фрейм данных с:

 import pandas as pd
import numpy as np  # for test data

data = {'Post ID': ['row1', 'row2', 'row3', 'row4', 'row5', 'row6', 'row7', 'row8'], 'Submission_Date': ['01.12.2020', '03.12.2020', '03.12.2020', '03.12.2020', '06.12.2020', '07.12.2020', '31.12.2020', '01.01.2021'], 'Flair': [np.nan, 'Discussion', 'News', 'Discussion', 'Due Diligence', 'Discussion', 'Discussion', 'Hedge Fund Tears']}
df = pd.DataFrame(data)

df['Submission_Date'] = pd.to_datetime(df['Submission_Date'], format = "%Y-%m-%d %H:%M:%S").dt.strftime('%Y-%m-%d') 

df = df.groupby('Submission_Date')['Flair'].value_counts(normalize=True).unstack()
 

В результате получается следующее:

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

Я хочу заполнить даты «пустыми» столбиками и построить такой график

что-то вроде этого:

Я уже пробовал это:

 fig, ax = plt.subplots(figsize=(20,10))
df.plot(kind='bar',ax=ax, stacked=True, width=1)
plt.xlabel('Submission_Date', fontsize=16)
plt.ylabel('Ratio of Flairs used', fontsize=16)
 

Но даты указаны неверно, так как пустые дни не отображаются

этот график

Комментарии:

1. Ты имеешь в виду df.groupby('Submission_Date')['Flair'].value_counts(normalize=True).unstack("Flair").plot.bar(stacked=True) ?

2. Чтобы включить пустые даты, которые вы могли бы использовать .resample('1D') перед командой p lot

3. @cripcate повторная выборка не будет работать, так как даты не определены индексом. Кроме того, даты содержат дубликаты: «Ошибка типа: Действительна только для DatetimeIndex, TimedeltaIndex или PeriodIndex, но получен экземпляр»Индекса»»

4. Хорошо. У меня не было времени написать более подробный ответ. Поэтому, чтобы это сработало, вам нужно создать submission_date (только) индекс, а затем выполнить повторную выборку с ежедневной частотой для каждого Flair , прежде чем выполнять группировку/подсчет значений/график

5.@cripcate Спасибо за ответ! Это звучит правильно. Однако у меня есть некоторые трудности: df['Submission_Date'] = pd.to_datetime(df['Submission_Date'], format = "%Y-%m-%d %H:%M:%S").dt.strftime('%Y-%m-%d') df.set_index('Submission_Date', inplace=True, drop=True) df df.index = pd.to_datetime(df.index, format = '%Y-%m-%d').strftime('%Y-%m-%d') df.index.name = None isinstance(df, pd.DatetimeIndex) возвращает False, поэтому submission_date не может быть отформатирован как единственный индекс 🙁

Ответ №1:

Предполагая, что этот ввод df2 (результат вашей groupby операции):

 Flair            Discussion  Due Diligence  Hedge Fund Tears      News
Submission_Date                                                       
01.01.2021              NaN            NaN               1.0       NaN
03.12.2020         0.666667            NaN               NaN  0.333333
06.12.2020              NaN            1.0               NaN       NaN
07.12.2020         1.000000            NaN               NaN       NaN
31.12.2020         1.000000            NaN               NaN       NaN
 

Вы можете reindex с pd.date_range :

 df2.index = pd.to_datetime(df2.index, format='%d.%m.%Y')
df2 = df2.reindex(pd.date_range(df2.index.min(), df2.index.max()))
df2.index = df2.index.strftime('%Y-%m-%d') 
 
 Flair       Discussion  Due Diligence  Hedge Fund Tears      News
2020-12-03    0.666667            NaN               NaN  0.333333
2020-12-04         NaN            NaN               NaN       NaN
2020-12-05         NaN            NaN               NaN       NaN
2020-12-06         NaN            1.0               NaN       NaN
2020-12-07    1.000000            NaN               NaN       NaN
...
2020-12-30         NaN            NaN               NaN       NaN
2020-12-31    1.000000            NaN               NaN       NaN
2021-01-01         NaN            NaN               1.0       NaN
 

графический результат (небольшой размер):

пропущенные даты