Home > Software engineering >  Matplotlib: Broken_barh plot, segment based on time, not hard coding the width
Matplotlib: Broken_barh plot, segment based on time, not hard coding the width

Time:01-21

Trying to get a result similar to the below link (but only one row of bars):

Matplotlib: How to use timestamps with broken_barh?

Instead of hard coding the bar width (as per example), im trying to segment based on time .

2023-01-18 06:00:00

2023-01-19 00:00:00
2023-01-18 07:00:00

2023-01-19 03:00:00
2023-01-18 08:00:00

2023-01-19 01:00:00
2023-01-18 09:00:00

2023-01-19 05:00:00
2023-01-18 13:00:00

2023-01-19 06:00:00
2023-01-18 14:00:00

2023-01-18 19:00:00
2023-01-18 18:00:00

2023-01-18 18:00:00

 

When printing 'i', end has the same number:

([(465006, 465028)], 22)
([(465008, 465026)], 20)
([(465009, 465025)], 23)
([(465010, 465010)], 19)
([(465011, 465029)], 18)
([(465012, 465022)], 21)
([(465013, 465030)], 24)
 

Not sure what's going on, any assistant appreciated.

Code:

import numpy as np
import matplotlib.pylab as plt
import pandas as pd


def make_broken_barhs(df):

    barh = []
    id_loc = []
    for loc in df['ID Location'].unique().tolist():
        date_idx = df.index[df['ID Location'] == loc].tolist()
        print(date_idx[0] )
        print()
        print(date_idx[-1])

        st = date_idx[0].to_period('h').ordinal
        ed = date_idx[-1].to_period('h').ordinal
        bar = [(st, ed)]
        barh.append(bar)
        id_loc.append(loc)
    return barh, id_loc


def plot_df(df):
    i, j = make_broken_barhs(df)
    ax = df.plot()

    for i in zip(i, j):
        ax.broken_barh(i[0], [19, .2], facecolor='red', linewidth=i[1])
    
    plt.show()

idx = pd.date_range('2023-01-18 06:00:00', '2023-01-19 06:00:00', freq='h')
df = pd.DataFrame({'ID Location': np.random.randint(low=18, high=25, size=(len(idx),))}, 
index=idx)

plot_df(df)

EDIT: Assigned incorrect variable to ed = date_idx[-1].to_period('h').ordinal, however, still shows a continuous bar, not segmented.

CodePudding user response:

Thei[0] segments in the broken_barth ax.broken_barh(i[0], [19, .2], facecolor='red', linewidth=i[1]) are in the wrong format.

This is because i[0] is composed of [startplace,endplace]. Instead i[0] should be build like this: [startplace,length_of_bar] where length_of_bar=endplace-startplace

try the code bellow. i additionally gave each ax.broken_barh a different y value to visualize it more clearly.

import numpy as np
import matplotlib.pylab as plt
import pandas as pd


def make_broken_barhs(df):
    barh = []
    id_loc = []
    for loc in df['ID Location'].unique().tolist():
        date_idx = df.index[df['ID Location'] == loc].tolist()
        print(date_idx[0])
        print()
        print(date_idx[-1])

        st = date_idx[0].to_period('h').ordinal
        ed = date_idx[-1].to_period('h').ordinal
        len_bar=ed-st
        bar = [(st, len_bar)]
        barh.append(bar)
        id_loc.append(loc)
    return barh, id_loc


def plot_df(df):
    i, j = make_broken_barhs(df)
    print(i,j)
    ax = df.plot()
    z=19
    for item in i:
        z =1
        ax.broken_barh(item, [z, 0.2], facecolor='red', linewidth=j[1])

    plt.show()


idx = pd.date_range('2023-01-18 06:00:00', '2023-01-19 06:00:00', freq='h')
df = pd.DataFrame({'ID Location': np.random.randint(low=18, high=25, size=(len(idx),))},
                  index=idx)

plot_df(df)
  • Related