1

I recently came across holoviews as promising visualization library in python and - as a practice - I wanted to transfer some of my existing code to see how it looks like in hv. I reached a given plot which I am unable to recreate.

I'd like to visualize a timeline or roadmap where the x axis is with type of pd.datetime and the y is categorical. Something like this:

enter image description here

What Element shall I use? How shall I define start and end position for sections?

doodoroma
  • 157
  • 2
  • 11

2 Answers2

4

HoloViews >= 1.13 now has hv.Segments().
This makes it a lot easier to create a Gantt chart:

from datetime import datetime
import holoviews as hv
hv.extension('bokeh')

data = {
    'start': [datetime(2018, 1,  3), datetime(2018, 3,  3), datetime(2018, 7, 15)],
    'end': [datetime(2018, 1, 31), datetime(2018, 3, 30), datetime(2018, 9, 23)],
    'start_event': ['Event1', 'Event2', 'Event2'],
    'end_event': ['Event1', 'Event2', 'Event2'],   
}

df = pd.DataFrame(data)

hv.Segments(
    data=df,
    kdims=['start', 'start_event', 'end', 'end_event']
).opts(line_width=4., width=1000)

Gantt Chart with HoloViews Segments

Sander van den Oord
  • 10,986
  • 5
  • 51
  • 96
  • is it supported by plotly backend? – Claire Dec 18 '20 at 02:20
  • 1
    it seems not, only seems to work for the Bokeh backend. You can test this by doing: hv.extension('plotly') vs hv.extension('bokeh') – Sander van den Oord Dec 18 '20 at 07:55
  • thanks. i tried with the cantor function from the [holoviews Segments document](https://holoviews.org/reference/elements/bokeh/Segments.html). The plot did show, with unshared opts dropped of coz, but much slower with plotly backend (30 s vs 4 s) at least in VSCode on my computer, but I was building with Dash. A bit tempted to stay. – Claire Dec 18 '20 at 08:30
2

This sounds like you need a Gantt chart.
I am using hv.Curve() drawing a line from the starting point in time to the end point in time:

# import libraries
from datetime import datetime
import holoviews as hv
hv.extension('bokeh')

# drawing a simple line
line1 = hv.Curve([
    [datetime(2018, 1,  3), 'Event1'],
    [datetime(2018, 1, 31), 'Event1'],
])

# creating a dashed line
line2 = hv.Curve([
    [datetime(2018, 3,  3), 'Event2'],
    [datetime(2018, 3, 30), 'Event2'],
]).opts(line_dash='dashed')

# creating a black thicker line
line3 = hv.Curve([
    [datetime(2018, 7, 15), 'Event2'],
    [datetime(2018, 9, 23), 'Event2'],
]).opts(color='black', line_width=10.0)

# add all 3 lines together on 1 plot with the * symbol
# this creates an overlay
gantt_chart = (line1 * line2 * line3)

# change xlim and width of the whole chart and add xlabel
# just making the plot a bit nicer
gantt_chart.opts(
    width=800, 
    xlim=(datetime(2018, 1, 1), datetime(2018, 12, 31)),
    xlabel='start to stop',
    ylabel='',
)

As you can see I've also added some options as an example to change the style of the lines and change the range of the x-axis.

Example code gives you this graph: enter image description here

Another solution is a more generic way of generating this Gantt plot, which loops over the data and generates a curve for every start/stop point:

# import libraries
from datetime import datetime
import holoviews as hv
hv.extension('bokeh')

# create sample data
data = [
    [datetime(2018, 1, 3), datetime(2018, 1, 31), 'Event1'],
    [datetime(2018, 3, 3), datetime(2018, 3, 30), 'Event2'],   
    [datetime(2018, 7, 15), datetime(2018, 9, 23), 'Event2'],
]

# loop over data to create a list with a line/curve for every start/stop point
all_lines_list = [
    hv.Curve([
        [row[0], row[2]],
        [row[1], row[2]],
    ]).opts(color='red') for row in data
]

# put all lines in an Overlay plot that can display all lines on 1 plot
gantt_chart = hv.Overlay(all_lines_list)

# make plot nicer
gantt_chart.opts(
    show_legend=False,
    width=800,
    xlim=(datetime(2018, 1, 1), datetime(2018, 12, 31)),
    xlabel='start to stop',
    ylabel='',
)
Sander van den Oord
  • 10,986
  • 5
  • 51
  • 96