#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 lot3. @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
графический результат (небольшой размер):