How to retain non-numeric labels, axes ticks and colorbar when converting matplotlib figures into plot figures with 'mpl_to_plt'?

To give a simple example, say we plot the following dataframe with non-numeric axes ticks:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.cm import coolwarm

data = {'Col1':['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
        'Col2':['1000', '2000', '3000', '4000', '5000', '6000', '7000', '8000', '9000', '10000']}
df = pd.DataFrame(data, columns=['Col1', 'Col2'])

fig, ax = plt.subplots()

s = ax.scatter(df.Col1, df.Col2, c=df.Col2, cmap=coolwarm)
plt.colorbar(s)

This plots the following figure. The non-numeric x- and y-ticks can be seen:
enter image description here

Now I want to convert it into a plotly figure.

from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.tools as tls

plotly_fig = tls.mpl_to_plotly(fig)

init_notebook_mode(connected=True)
iplot(plotly_fig)

enter image description here

As can be seen, the x- and y-ticks are now replaced with dummy numeric values, and the colorbar is missing entirely. How to prevent this from happening during conversion? Or, if that can’t be done, how do I add back the correct x- and y-ticks in the plotly figure?


Here are the contents of plotly_fig:

Figure({
    'data': [{'marker': {'color': [rgba(58,76,192,1.0), rgba(92,123,229,1.0),
                                   rgba(130,165,251,1.0), rgba(170,198,253,1.0),
                                   rgba(205,217,236,1.0), rgba(234,211,199,1.0),
                                   rgba(246,183,156,1.0), rgba(240,141,111,1.0),
                                   rgba(217,88,71,1.0), rgba(179,3,38,1.0)],
                         'line': {'color': [rgba(58,76,192,1.0),
                                            rgba(92,123,229,1.0),
                                            rgba(130,165,251,1.0),
                                            rgba(170,198,253,1.0),
                                            rgba(205,217,236,1.0),
                                            rgba(234,211,199,1.0),
                                            rgba(246,183,156,1.0),
                                            rgba(240,141,111,1.0),
                                            rgba(217,88,71,1.0),
                                            rgba(179,3,38,1.0)],
                                  'width': 1.0},
                         'size': 6.0,
                         'symbol': 'circle'},
              'mode': 'markers',
              'type': 'scatter',
              'uid': '75c3c5d8-cdfd-11e8-a124-8c164500f4c6',
              'x': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
              'xaxis': 'x',
              'y': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
              'yaxis': 'y'}],
    'layout': {'autosize': False,
               'height': 288,
               'hovermode': 'closest',
               'margin': {'b': 36, 'l': 54, 'pad': 0, 'r': 82, 't': 34},
               'showlegend': False,
               'width': 432,
               'xaxis': {'anchor': 'y',
                         'domain': [0.0, 0.9065431948336785],
                         'mirror': 'ticks',
                         'nticks': 10,
                         'range': [-0.45108422939068105, 9.451084229390682],
                         'showgrid': False,
                         'showline': True,
                         'side': 'bottom',
                         'tickfont': {'size': 10.0},
                         'ticks': 'inside',
                         'type': 'linear',
                         'zeroline': False},
               'xaxis2': {'anchor': 'y2',
                          'domain': [0.9632021445107835, 1.0],
                          'mirror': False,
                          'nticks': 0,
                          'range': [0.0, 1.0],
                          'showgrid': False,
                          'showline': False,
                          'side': 'bottom',
                          'ticks': 'inside',
                          'type': 'linear',
                          'zeroline': False},
               'yaxis': {'anchor': 'x',
                         'domain': [0.0, 1.0],
                         'mirror': 'ticks',
                         'nticks': 10,
                         'range': [-0.4516694260485652, 9.451669426048566],
                         'showgrid': False,
                         'showline': True,
                         'side': 'left',
                         'tickfont': {'size': 10.0},
                         'ticks': 'inside',
                         'type': 'linear',
                         'zeroline': False},
               'yaxis2': {'anchor': 'x2',
                          'domain': [1.4704940723512008e-16, 1.0],
                          'dtick': 0.1111111111111111,
                          'mirror': False,
                          'range': [0.0, 1.0],
                          'showgrid': False,
                          'showline': False,
                          'side': 'right',
                          'tick0': 0.0,
                          'tickfont': {'size': 10.0},
                          'ticks': 'inside',
                          'type': 'linear',
                          'zeroline': False}}
})

Addendum: After checking here and here, I wrote the following code to add a colorscale and a colorbar for the plotly figure:

plotly_fig['data'][0]['marker']['colorbar'] = dict(title='Scatter point value', 
                                                   tickvals=[min(plotly_fig['data'][0]['x']), max(plotly_fig['data'][0]['x'])],
                                                   ticktext = ['Low', 'High'],
                                                   ticks = 'outside',
                                                   titleside = 'right', # possible options ['right', 'top', 'bottom']
                                                   tickmode = 'array') 

plotly_fig['data'][0]['marker']['colorscale']= [[0.0, 'rgb(165,0,38)'], [0.1111111111111111, 'rgb(215,48,39)'], [0.2222222222222222, 'rgb(244,109,67)'],
        [0.3333333333333333, 'rgb(253,174,97)'], [0.4444444444444444, 'rgb(254,224,144)'], [0.5555555555555556, 'rgb(224,243,248)'],
        [0.6666666666666666, 'rgb(171,217,233)'],[0.7777777777777778, 'rgb(116,173,209)'], [0.8888888888888888, 'rgb(69,117,180)'],
        [1.0, 'rgb(49,54,149)']]

However, only the colorbar works, that too partially (as the High value specified in the code is not shown in the plotted colorbar, only the Low is shown), and the colors don’t appear in the colorbar:

enter image description here

Best for #api:python

Right now, the only workaround I have found is to first plot a dummy scatterplot with -

  1. a similar looking colormap (for example, to my eyes at least, the equivalent of matplotlib’s coolwarm seems to be plotly’s RdBu),
  2. a similar range of values that are going to be on the y-axis (like, 1000 to 11000), to ensure that the colorbar’s limits appear correctly, and
  3. the axis titles, if you want them.

Like so:

import numpy as np
import plotly.graph_objs as go

z=np.random.randint(1000, 11000, size=20)
trace=dict(type='scatter',
          x=3+np.random.rand(20),
          y=-2+3*np.random.rand(20),
          mode='markers',
          marker=dict(color= z, 
                      colorscale='RdBu', size=14, colorbar=dict(thickness=20)))

axis_style=dict(zeroline=False, showline=True, mirror=True)
layout=dict(width=600, height=450,
            xaxis=axis_style,
            yaxis=axis_style,
           hovermode='closest')
fig=go.FigureWidget(data=[trace], layout=layout)
fig

enter image description here

And then update the figure trace with the real data, which then produces the axes ticks and the colorbar correctly:

trace.update(dict(x=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], 
                  y=['1000', '2000', '3000', '4000', '5000', '6000', '7000', '8000', '9000', '10000']
                 )
            )

fig=go.FigureWidget(data=[trace], layout=layout)
fig

enter image description here

But it shouldn’t be this convoluted. Not to mention that in real cases, I wouldn’t know the actual x- and y-values to update a dummy graph with, which is why I am plotting them in matplotlib (as the library that produces these plots were designed to plot matplotlib figures only) and then converting them to plotly.

But anyway, just posting the workaround here, in case it helps anyone else facing the same problem.