8

I want to create a lollipop plot with several horizontal line segments like this - https://python-graph-gallery.com/184-lollipop-plot-with-2-group. I'd like to use plotly since I prefer the graphics (and easy interactivity) but can't find a succint way.

There's both line graphs (https://plot.ly/python/line-charts/) and you can add lines in the layout (https://plot.ly/python/shapes/#vertical-and-horizontal-lines-positioned-relative-to-the-axes), but both of these solutions require each line segment to be added separately, with about 4-8 lines of code each. While I could just for-loop this, would appreciate if anyone can point me to anything with inbuilt vectorization, like the matplotlib solution (first link)!

Edit: Also tried the following code, to first make the plot ala matplotlib, then convert to plotly. The line segments disappear in the process. Starting to think it's just impossible.

mpl_fig = plt.figure()

# make matplotlib plot - WITH HLINES
plt.rcParams['figure.figsize'] = [5,5]
ax = mpl_fig.add_subplot(111)
ax.hlines(y=my_range, xmin=ordered_df['value1'], xmax=ordered_df['value2'], 
color='grey', alpha=0.4)
ax.scatter(ordered_df['value1'], my_range, color='skyblue', alpha=1, 
label='value1')
ax.scatter(ordered_df['value2'], my_range, color='green', alpha=0.4 , 
label='value2')
ax.legend()

# convert to plotly
plotly_fig = tls.mpl_to_plotly(mpl_fig)
plotly_fig['layout']['xaxis1']['showgrid'] = True
plotly_fig['layout']['xaxis1']['autorange'] = True
plotly_fig['layout']['yaxis1']['showgrid'] = True
plotly_fig['layout']['yaxis1']['autorange'] = True

# plot: hlines disappear :/
iplot(plotly_fig)

2 Answers 2

10

You can use None in the data like this:

import plotly.offline as pyo
import plotly.graph_objs as go

fig = go.Figure()

x = [1, 4, None, 2, 3, None, 3, 4]
y = [0, 0, None, 1, 1, None, 2, 2]

fig.add_trace(
    go.Scatter(x=x, y=y))
    
pyo.plot(fig)

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

8

Plotly doesn't provide a built in vectorization for such chart, because it can be done easily by yourself, see my example based on your provided links:

import pandas as pd
import numpy as np
import plotly.offline as pyo
import plotly.graph_objs as go

# Create a dataframe
value1 = np.random.uniform(size = 20)
value2 = value1 + np.random.uniform(size = 20) / 4
df = pd.DataFrame({'group':list(map(chr, range(65, 85))), 'value1':value1 , 'value2':value2 })

my_range=range(1,len(df.index)+1)

# Add title and axis names
data1 = go.Scatter(
        x=df['value1'],
        y=np.array(my_range),
        mode='markers',
        marker=dict(color='blue')
    )


data2 = go.Scatter(
        x=df['value2'],
        y=np.array(my_range),
        mode='markers',
        marker=dict(color='green')
    )

# Horizontal line shape
shapes=[dict(
        type='line',
        x0 = df['value1'].loc[i],
        y0 = i + 1,
        x1 = df['value2'].loc[i],
        y1 = i + 1,
        line = dict(
            color = 'grey',
            width = 2
        )
    ) for i in range(len(df['value1']))]


layout = go.Layout(
    shapes = shapes,
    title='Lollipop Chart'
)

# Plot the chart
fig = go.Figure([data1, data2], layout)

pyo.plot(fig)

With the result I got:

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.