Comment créer un graphique à barres empilées avec une série chronologique et des valeurs agrégées

Nov 25 2020

J'ai des difficultés à créer une série chronologique de graphique à barres empilées à partir de ma trame de données Pandas (image ci-dessous). Je voudrais avoir la «Date» sur l'axe des x, les «Heures» sur l'axe des y et chaque barre pour afficher le temps passé avec chaque groupe dans «Catégorie».

Dois-je utiliser Pandas - Fonction Groupby? Le dataframe est un exemple. J'ai des centaines de lignes de données de 2018 à 2020.

Réponses

3 TrentonMcKinney Nov 25 2020 at 07:35
  • Il existe une solution aux pandas: un graphique à barres empilées avec des données chronologiques
    • Le problème avec cette question, c'est que OP n'agrège aucune donnée, donc cette solution ne fonctionne pas pour cette question.
  • Utiliser pandas.DataFrame.groupbysur 'date'et 'group', lors de l'agrégation .sumsur'time'
    • L' .dtextracteur est utilisé pour extraire uniquement le .datecomposant de la 'date'colonne.
    • Assurez-vous que la 'Date'colonne de votre dataframe est correctement formatée en tant que datetime dtype, avecdf.Date = pd.to_datetime(df.Date)
  • Le dataframe groupé,, dfgdoit être mis en forme dans la forme correcte, ce qui peut être accompli avec pandas.DataFrame.pivot.
  • Le moyen le plus simple d'empiler un graphique à barres consiste à pandas.DataFrame.plot.barutiliser le stackedparamètre.
    • Voir pandas.DataFrame.plotpour tous les paramètres.
import pandas as pd
import matplotlib.pyplot as plt
import random  # for test data
import numpy as np  # for test data

# setup dataframe with test data
np.random.seed(365)
random.seed(365)
rows = 1100
data = {'hours': np.random.randint(10, size=(rows)),
        'group': [random.choice(['A', 'B', 'C']) for _ in range(rows)],
        'date': pd.bdate_range('2020-11-24', freq='h', periods=rows).tolist()}
df = pd.DataFrame(data)

# display(df.head())
   hours group                date
0      2     C 2020-11-24 00:00:00
1      4     B 2020-11-24 01:00:00
2      1     C 2020-11-24 02:00:00
3      5     A 2020-11-24 03:00:00
4      2     B 2020-11-24 04:00:00

# use groupby on df
dfg = df.groupby([df.date.dt.date, 'group'])['hours'].sum().reset_index()

# pivot the dataframe into the correct format
dfp = dfg.pivot(index='date', columns='group', values='hours')

# display(dfp.head())
group        A   B   C
date                  
2020-11-24  49  25  29
2020-11-25  62  18  57
2020-11-26  42  77   4
2020-11-27  34  43  17
2020-11-28  28  53  23

# plot the pivoted dataframe
dfp.plot.bar(stacked=True, figsize=(10, 6), ylabel='Hours', xlabel='Date', title='Sum of Daily Category Hours')
plt.legend(title='Category', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()

  • Il y aura une barre pour chaque jour, c'est ainsi que fonctionnent les graduations des graphiques à barres, de sorte que le graphique peut être très large, s'il y a plusieurs dates.
  • Pensez à utiliser pandas.DataFrame.barh
dfp.plot.barh(stacked=True, figsize=(6, 10), title='Sum of Daily Category Hours')
plt.legend(title='Category', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.xlabel('Hours')
plt.ylabel('Date')
plt.show()

  • L'OP indique qu'il existe des données de 2018 à 2020, ce qui signifie qu'il pourrait y avoir plus de 700 jours de données, ce qui se traduit par plus de 700 barres dans le graphique à barres.
  • Un tracé linéaire standard peut être la meilleure option pour visualiser correctement les données.
dfp.plot(figsize=(10, 6))
plt.show()