4

I have to plot lines on multiple y-axes. In plotly, however, the axis generation within go.Layout is quite verbose like in this example from the plotly documentation: https://plot.ly/python/multiple-axes/

layout = go.Layout(
title='multiple y-axes example',
width=800,
xaxis=dict(
    domain=[0.3, 0.7]
),
yaxis=dict(
    title='yaxis title',
    titlefont=dict(
        color='#1f77b4'
    ),
    tickfont=dict(
        color='#1f77b4'
    )

## repeat for every new y-axis.

In matplotlib i like to save code by generating all the different axes and handling the plotting in loops like so:

import matplotlib.pyplot as plt
import numpy as np

# generate dummy data
data = []
for i in range(5):
    arr = np.random.random(10) * i
    data.append(arr)

colors = ['black', 'red', 'blue', 'green', 'purple']
labels = ['label1', 'label2', 'label3', 'label4', 'label5']

# define other paramters (e.g. linestyle etc.) in lists

fig, ax_orig = plt.subplots(figsize=(10, 5))
for i, (arr, color, label) in enumerate(zip(data, colors, labels)):
    if i == 0:
        ax = ax_orig
    else:
        ax = ax_orig.twinx()
        ax.spines['right'].set_position(('outward', 50 * (i - 1)))
    ax.plot(arr, color=color, marker='o')
    ax.set_ylabel(label, color=color)
    ax.tick_params(axis='y', colors=color)
fig.tight_layout()
plt.show()

figure generated by example

Due to the dict-syntax used in object generation I seem to be unable to make something like that work in plotly. I have tried generating the axes-dicts by loops in advance and passing those to go.Layout but with no success. If anybody could point out an elegant way to reduce redundancy it will be greatly appreciated.

All the best and thanks in advance.

1 Answer 1

7

You could take advantage of Python's **kwargs, i.e. you create a dictionary which contains all your layout values and passes it to Plotly's layout.

import numpy as np
import plotly

plotly.offline.init_notebook_mode()

# generate dummy data, taken from question
data = []
for i in range(5):
    arr = np.random.random(10) * i
    data.append(arr)

labels = ['label1', 'label2', 'label3', 'label4', 'label5']

plotly_data = []
plotly_layout = plotly.graph_objs.Layout()

# your layout goes here
layout_kwargs = {'title': 'y-axes in loop',
                 'xaxis': {'domain': [0, 0.8]}}

for i, d in enumerate(data):
    # we define our layout keys by string concatenation
    # * (i > 0) is just to get rid of the if i > 0 statement
    axis_name = 'yaxis' + str(i + 1) * (i > 0)
    yaxis = 'y' + str(i + 1) * (i > 0)
    plotly_data.append(plotly.graph_objs.Scatter(y=d, 
                                                 name=labels[i]))
    layout_kwargs[axis_name] = {'range': [0, i + 0.1],
                                'position': 1 - i * 0.04}

    plotly_data[i]['yaxis'] = yaxis
    if i > 0:
        layout_kwargs[axis_name]['overlaying'] = 'y'

fig = plotly.graph_objs.Figure(data=plotly_data, layout=plotly.graph_objs.Layout(**layout_kwargs))
plotly.offline.iplot(fig)

enter image description here

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

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.