Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

traces selection/update methods and "magic underscore" support #1534

Merged
merged 13 commits into from
May 3, 2019

Conversation

jonmmease
Copy link
Contributor

@jonmmease jonmmease commented Apr 23, 2019

Closes #1481 and the trace portion of #1484.

Overview

This PR introduces 3 new figure methods to make it easier to make updates to traces that have already been added to a Figure (e.g. a Figure from plotly_express or a figure factory). It also introduces a convenient shorthand for updating nested properties that we've been calling "magic underscore" support.

New Figure methods

All 3 methods allow the user to select certain traces from the figure using a "selector". This is an update style dict that can be used to specify the desired values of arbitrary properties in the trace. For example, a selector of {'type': 'scatter'} will select all scatter traces in the figure. A selector of {'type': 'scatter', 'mode': 'markers'} will select only those scatter traces that are in 'markers' mode.

In addition to the selector, for figures created using plotly.subplots.make_subplots, the trace row and column index may also be used as selection criteria.

The lowest level method is select_traces. This returns a generator that iterates over all of the traces in the figure that satisfy the selection criteria.

The for_each_trace method applies a custom function to each trace produced by select_traces

The update_traces method accepts a "patch" to update all of the traces that satisfy the selection criteria. This "patch" is a dict that is passed to trace.update for all selected traces.

"Magic underscore" support

For background on "magic underscore" support, see #919 and #1481.

The goal of magic underscore support is to make it more convenient to reference nested figure properties without the need to created deeply nested dict instances.

Here are the updates that have been implemented:

Figure and graph_objs constructors

Here's a current approach to creating a figure with a particular title:

import plotly.graph_objs as go
fig = go.Figure(layout={'title': {'text': 'Hello, Figure'}})

With magic-underscore support:

fig = go.Figure(layout_title_text='Hello, Figure')

.update operations

Here's a current approach to updating the title text for an existing figure

fig = go.Figure()
fig.update(layout={'title': {'text': 'Hello, Figure'}})

with magic-underscore support:

fig = go.Figure()
fig.update(layout_title_text='Hello, Figure')

In addition to using underscores to separate nested keys, when the update argument is supplied as a dict (rather than as kwargs), the path parts can be separated by periods.

fig = go.Figure()
fig.update({'layout_title_text': 'Hello, Figure',
            'layout.title.font.color': 'green'})

add trace methods

Here's a current approach creating a scatter trace with green markers

fig = go.Figure()
fig.add_scatter(y=[2, 3, 1], mode='markers', marker={'color': 'green'})
fig

With magic underscore support

fig = go.Figure()
fig.add_scatter(y=[2, 3, 1], mode='markers', marker_color='green')
fig

compatibility

One tricky thing to keep track of is that there are a few properties in plotly.js that contain underscores in their proper name. e.g. scatter.error_y and layout.paper_bgcolor. These are kept track of as special cases.

Here's an example of using magic underscore logic alongside the error_y property:

fig = go.Figure()
fig.add_scatter(
    y=[2, 3, 1],
    mode='markers',
    marker_color='green',
    error_y_array=[2, 1, 3]
)
fig.update(data_0_error_y_color='blue')

Note how integer data array indices can be specified directly in the argument.

All together

Combining update_traces and magic-underscore support should make it much easier to selectively update trace properties.

For example, to update the line width of all scatter traces in line mode:

fig.update_traces({'line.width': 4}, selector={'type': 'scatter', 'mode': 'lines'})

Or, only the line traces in subplot position 2, 1

fig = make_subplots(3, 3, ...)
...
fig.update_traces({'line.width': 4}, selector={'type': 'scatter', 'mode': 'lines'}, row=2, col=1)

@jonmmease jonmmease added this to the v3.9.0 milestone Apr 23, 2019
The input `spec` was removed from the grid_ref to make it easier to
compare traces with the grid subplots
@nicolaskruchten
Copy link
Contributor

OMG this is such an exciting PR!!

@sglyon
Copy link

sglyon commented Apr 24, 2019

@jonmmease this is awesome. Thanks for reviving my old concept of magic underscore notation.

I’ve loved having it in my Julia library and seeing it here makes me 😁😁

Good work!

@jonmmease jonmmease merged commit 6ced2d9 into master May 3, 2019
@jonmmease
Copy link
Contributor Author

Merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Magic underscores
3 participants