1

Background:

I am stuck. Or just having a blonde moment. I'm like a deer looking at headlights.

I've queried the following dataframe from MySQL table.

date          operation
2020-05-07        A
2020-05-08        B
2020-05-08        A
2020-05-12        A
2020-05-12        A
2020-05-12        B
2020-05-13        C
2020-05-13        A
2020-05-13        B
2020-05-14        A
2020-05-19        B
2020-05-21        A
2020-05-25        A
2020-05-26        B
2020-05-26        C
2020-05-26        A
2020-05-26        A
2020-05-29        A

I have no idea how to make it a stacked bar chart with matplotlib.

Research:

  1. Grouped Bar-Chart with customized DateTime Index using pandas and Matplotlib
  2. Stacked bar plot using Matplotlib

Question:

How can I generate a stack-bar-chart with matplot lib with the above sample data?

Code snippet:

import datetime as dt
import mysql.connector
import os
import pandas as pd
# import numpy as np
import matplotlib.pyplot as plt
import datetime

def generate_monthly_graph():
    query = "SELECT [...]`"
    mycursor.execute(query)
    mycursor.execute(query)
    data = mycursor.fetchall()

    df = pd.DataFrame(data, columns=['date', 'operation'])

    df = df.set_index('date')

    df.index = pd.to_datetime(df.index)
3kstc
  • 1,871
  • 3
  • 29
  • 53

1 Answers1

3

You can use crosstab then plot.bar:

# convert to date, no need for set_index
df.date = pd.to_datetime(df.date)

pd.crosstab(df.date,df.operation).plot.bar(stacked=True)

Output:

enter image description here

If you want monthly, you can use dt.to_period('M') to get monthly dates and crosstab:

pd.crosstab(df.date.dt.to_period('M'),df.operation).plot.bar(stacked=True)

Output (for the sample data):

enter image description here


Update to have all the dates on the x-axis:

df['date'] = pd.to_datetime(df.date)

mindate, maxdate = df['date'].agg(['min','max'])

all_dates = pd.date_range(mindate, maxdate, freq='D').date

(pd.crosstab(df.date,df.operation)
   .reindex(all_dates)
   .plot.bar(stacked=True)
)

Output:

enter image description here

Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
  • with the daily one, how can I make it so everyday is shown in the x-axis, ie define the x limits `plt.xlim(datetime.date(2020, 5, 1), datetime.date(2020, 5, 31))` also, with this graph, my dates are appearing to be `00:00` – 3kstc Jun 03 '20 at 05:56
  • You can use [DayLocator](https://www.programcreek.com/python/example/71850/matplotlib.dates.DayLocator). – Quang Hoang Jun 03 '20 at 12:20
  • I'm struggling :( Any chance you could kindly update your answer and _write_ the whole code? Where one can define the title, x and y axis [custom] labels? please? – 3kstc Jun 04 '20 at 00:17
  • what about custom range like `datetime.date(2020, 5, 1), datetime.date(2020, 5, 31))` mentioned in my first comment – 3kstc Jun 04 '20 at 00:36
  • Replace `mindate` with ''2020-05-01'` and `maxdate` with `'2020-05-31'` in the definition of `all_dates`. – Quang Hoang Jun 04 '20 at 00:39
  • still struggling with some [issues](https://stackoverflow.com/questions/62205274/matplotlib-dataframe-2-column-dates-non-numerical-data-stacked-bar-chart-defi) – 3kstc Jun 05 '20 at 01:19
  • Any help please? – 3kstc Jun 05 '20 at 09:26