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

Proposed API for twin-axis support #5355

Closed
jlstevens opened this issue Jul 18, 2022 · 14 comments
Closed

Proposed API for twin-axis support #5355

jlstevens opened this issue Jul 18, 2022 · 14 comments
Assignees
Labels
type: feature A major new feature
Milestone

Comments

@jlstevens
Copy link
Contributor

jlstevens commented Jul 18, 2022

Twin axes is an often requested feature (e.g. see #396, #1594, #3011) and HoloViews should support this type of plot without having to resort to ugly custom hooks.

In this issue I would like to propose an API for discussion. In particular, I think the most intuitive approach would be to support twin-axes by creating a simple overlay, where one of the components has yaxis='twin' specified as a plot option. Right now, the possible values for yaxis (for bokeh) are ['left', 'right', None, True, False] which means 'twin' would be added to this list. For matplotlib, the options are ['left', 'right', None] (I don't see why true and False shouldn't also be supported here though!)

As 'left' and 'right' are already supported, using 'twin' would add axes on the opposite side for the component it is attached to. For instance:

  1. curve1 * curve2.opts(yaxis='twin'): curve1 has its yaxis on the left (default) and curve2 has its yaxis on the right
  2. curve1.opts(yaxis='right') * curve2.opts(yaxis='twin'): curve1 has its yaxis on the right and curve2 has its yaxis on the left

I think this would be intuitive enough given how everything currently works. In principle, this should support overlaying two NdOverlays so that you have two legends, one for each side.

Suggested rules:

  1. The x-axis dimension must match otherwise trying to use twin-axes should be an error.
  2. Twin axes make sense for a number of chart elements (e.g. curves, scatter) but I don't think they really make sense for Points and Paths which exist in a homogenous 2D space (where you can sensibly imagine rotations). I don't think this option will make sense for all element types (e.g. can this really be sensible for bar charts?)
@jlstevens jlstevens added TRIAGE Needs triaging type: feature A major new feature and removed TRIAGE Needs triaging labels Jul 18, 2022
@jlstevens jlstevens added this to the v2.0 milestone Jul 18, 2022
@maximlt
Copy link
Member

maximlt commented Jul 18, 2022

Allowing twin axes makes sense too for two elements that are not of the same type. E.g. in this example taken from Microsoft's site: https://support.microsoft.com/en-us/office/add-or-remove-a-secondary-axis-in-a-chart-in-excel-91da1e2f-5db1-41e9-8908-e1a2e14dd5a9#OfficeVersion=macOS
image

@jbednar
Copy link
Member

jbednar commented Jul 18, 2022

Twin axes make sense for a number of chart elements (e.g. curves, scatter) but I don't think they really make sense for Points and Paths which exist in a homogenous 2D space (where you can sensibly imagine rotations).

I agree that they don't make much sense for Points and Paths, nor for dense rasters or geo maps, but I wouldn't disallow those if it takes extra work to do so. It's hard to anticipate all the ways someone might use this functionality, some of which are abuses but others might end up useful.

I don't think this option will make sense for all element types (e.g. can this really be sensible for bar charts?)

It's hard to see overlaying two bar charts as useful since bar charts themselves already support stacking or side by side bars, but again, maybe not worth the effort of figuring out which ones are truly useless, and which ones are just rarely useful.

@jlstevens
Copy link
Contributor Author

I should also note (as @philippjfr pointed out to me) that we've had discussion about potential API before (e.g. in the issues I referenced above). Here, I've described the API that currently makes sense to me but we should revisit those issues as I am open to other possible suggestions...

@douglas-raillard-arm
Copy link
Contributor

douglas-raillard-arm commented Jul 29, 2022

Haven't put much thoughts in that but an alternative could be a 2nd overlay operator, e.g. the division (maybe it's already taken for something, haven't checked):

def __truediv__(self, other):
    return self * other.opts(yaxis='twin')

EDIT: fixed the code

@jlstevens
Copy link
Contributor Author

That would indeed be a possible approach but we are wary of adding new operators. In particular, we have discussed using / to improve the layout system (to define rows and columns more easily).

@douglas-raillard-arm
Copy link
Contributor

It's maybe a terrible idea but it just struck me that we actually can have an unlimited supply of infix operators in Python if we are ready to make pylint scream about the missing whitespaces:

class Meta(type):
    def __rlshift__(self, left):
        return self(left)

class Op(metaclass=Meta):
    def __init__(self, left):
        self.left = left

    def __rshift__(self, right):
        return self.op(self.left, right)


class Custom(Op):
    @staticmethod
    def op(left, right):
        return left * right

# We just created a new operator "<<Custom>>"
print(3 <<Custom>> 2)

@csgorham
Copy link

csgorham commented Aug 23, 2022

Trying to plot double BoxWhiskers with double y axis for 'height' and 'weight' ... running into so much trouble

def twinyy(plot, element):
    # Setting the second y axis range name and range
    #start, end = (element.range(1))
    label = element.dimensions()[1].pprint_label
    plot.state.extra_y_ranges = {"foo": Range1d(start=4, end=6)}
    # Adding the second axis to the plot. 
    linaxis = LinearAxis(axis_label='Height', y_range_name='foo')
    plot.state.add_layout(linaxis, 'right')
    
    
title = "Weight and Height of Club Members"

boxwhisker1 = hv.BoxWhisker(teams_fifa , 
                            'Club', 'Weight', label=title).opts(show_legend=False, width=600, 
                                                              box_fill_color='Blue', box_line_color='Blue')
boxwhisker2 = hv.BoxWhisker(teams_fifa , 
                           'Club', 'Height', label=title).opts(show_legend=False, width=600, 
                                                              box_fill_color='Red', box_line_color='Red', hooks=[twinyy])

boxwhisker1*boxwhisker2

<img width="503" alt="Screen Shot 2022-08-22 at 9 30 36 PM" src="https://user-images.githubusercontent.com/3809336/186048641-3a23ef93-4c2a-4ec3-b9a8-230c1d35fc46.png">

@jlstevens
Copy link
Contributor Author

Unfortunately, HoloViews does not support twin axes well right now and any workarounds that might work aren't great. We do want to support it better in the future though!

@MarcSkovMadsen
Copy link
Collaborator

There is a user requesting it here https://discourse.holoviz.org/t/how-to-implement-secondary-y-axis/4317/2

I also need it for my use cases.

@LinuxIsCool
Copy link

This is an essential feature for holoviews in my opinion. I do need this feature in my workflow.

@jbednar
Copy link
Member

jbednar commented Dec 8, 2022

It's a funded task on our list, so I hope we'll get to it soon, but we do have a bunch of priorities to juggle, so it's hard to promise anything!

@Episkiliski
Copy link

Hi, is there any development on this?

In my line of work this is crucial, for example to plot Temperature in Primary y-axis (left) and Pressure in Secondary y-axis (right) with Time in the x-axis. This is not allowing me to use HvPlot unfortunately.

Thanks!

@jlstevens
Copy link
Contributor Author

There is! Thank you for bumping this issue!

Sorry, I should have referenced this issue in the PR that was merged (and now released): #5621

The API is to use multi_y=True on an overlay and you can find more docs here: https://holoviews.org/user_guide/Customizing_Plots.html#twin-axes

Closing.

@Episkiliski
Copy link

There is! Thank you for bumping this issue!

Sorry, I should have referenced this issue in the PR that was merged (and now released): #5621

The API is to use multi_y=True on an overlay and you can find more docs here: https://holoviews.org/user_guide/Customizing_Plots.html#twin-axes

Closing.

Thanks, does it have direct application in HvPlot?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature A major new feature
Projects
None yet
Development

No branches or pull requests

9 participants