0

How to plot start/end time pair in pandas like the following?I need a plot to easily show which step from when, and how long it is.

data = [['set1', 0,10], ['step2', 3,12], ['step3', 8,15]]
df = pd.DataFrame(data, columns=['name', 'start','end'])

enter image description here

Daniel Wu
  • 5,853
  • 12
  • 42
  • 93
  • It is not possible to provide a specific answer without you providing sufficient information to understand your problem. Please see: [Why is Can someone help me? not an actual question?](https://meta.stackoverflow.com/questions/284236/why-is-can-someone-help-me-not-an-actual-question) for more details. – itprorh66 Aug 04 '23 at 13:23

2 Answers2

1

A quite similar effect can be achieved with horizontal bar (stacked) plot:

ax = df.plot(kind='barh', stacked=True)
ax.set_xticks(range(0, df[['start','end']].sum(1).max() + 1, 1))

enter image description here

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
1

The code below provides similar functionality. Not sure if it's exactly what you were after. Bars have a uniform colour rather than being segmented.

enter image description here

from matplotlib import patches
import numpy as np

#
# Example data
#

#Original data
data = [['set1', 0, 10], ['step2', 3, 12], ['step3', 8, 15]]
df = pd.DataFrame(data, columns=['name', 'start', 'end'])

#Data with more steps
df = pd.DataFrame(
    {
        step: [start, start + duration]
        for step, start, duration in
        zip([f'step_{i}' for i in range(30)],
            0.5 * np.random.randn(30) + np.arange(0, 30),
            np.random.uniform(5, 10, (30,))
            )
    },
    index=['start', 'end']
).T.reset_index()
df.rename(columns={'index': 'name'}, inplace=True)

#
# Create plot
#
height = 0.9

f, ax = plt.subplots(figsize=(10, 6))
for idx in range(len(df)):
    y0 = (idx + 1) - height / 2
    x0 = df.iloc[idx].start
    width = df.iloc[idx].end - x0
    ax.add_patch( patches.Rectangle((x0, y0), width, height) )
    ax.hlines(y0 + height / 2,
              xmin=df.start.min(),
              xmax=x0,
              color='k', linestyles=':', linewidth=0.5)
    
ax.axis((df.start.min(), df.end.max(), 1 - height, len(df) + height))
ax.set_xlabel('time')
ax.set_ylabel('name')
ax.set_yticks(range(1, len(df) + 1))
ax.set_yticklabels(df.name)
plt.show()
some3128
  • 1,430
  • 1
  • 2
  • 8