Jak utworzyć skumulowany wykres słupkowy z szeregami czasowymi i zagregowanymi wartościami

Nov 25 2020

Mam trudności z utworzeniem szeregu czasowego skumulowanego wykresu słupkowego na podstawie mojej ramki danych Pandas (ilustracja poniżej). Chciałbym mieć „Data” na osi X, „Godziny” na osi Y i każdy słupek, aby pokazywał czas spędzony z każdą grupą w „Kategorii”.

Czy muszę korzystać z funkcji Pandas - Groupby? Ramka danych to próbka. Mam setki wierszy danych od 2018 do 2020 roku.

Odpowiedzi

3 TrentonMcKinney Nov 25 2020 at 07:35
  • Jest jedno rozwiązanie dla pand - skumulowany wykres słupkowy z danymi z serii timeeries
    • Problem z tym pytaniem polega na tym, że OP nie agreguje żadnych danych, więc to rozwiązanie nie działa w przypadku tego pytania.
  • Użyj pandas.DataFrame.groupbyon 'date'i 'group', podczas agregacji .sumon'time'
    • .dtWyciąg jest stosowany do ekstrakcji tylko .dateskładnik 'date'kolumny.
    • Upewnij się, że 'Date'kolumna ramki danych jest poprawnie sformatowana jako datetime dtype, zdf.Date = pd.to_datetime(df.Date)
  • Zgrupowaną ramkę danych dfgnależy uformować do odpowiedniej postaci, co można osiągnąć za pomocą pandas.DataFrame.pivot.
  • Najłatwiejszym sposobem ułożenia wykresu słupkowego jest pandas.DataFrame.plot.barużycie stackedparametru.
    • Zobacz pandas.DataFrame.plotwszystkie parametry.
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()

  • Na każdy dzień będzie pasek, tak działają znaczniki wykresu słupkowego, więc wykres może być bardzo szeroki, jeśli jest wiele dat.
  • Rozważ użycie 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()

  • W PO podano, że istnieją dane z lat 2018-2020, co oznacza, że ​​mogą istnieć dane z ponad 700 dni, co przekłada się na ponad 700 słupków na wykresie słupkowym.
  • Standardowy wykres liniowy może być najlepszą opcją do poprawnej wizualizacji danych.
dfp.plot(figsize=(10, 6))
plt.show()