plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.
https://plotly.com/dash
MIT License
21.48k stars 2.07k forks source link

Send categorical color data on click/hover/select #2738

Open Voltini opened 9 months ago

Voltini commented 9 months ago

Hi there, I just discovered Dash recently and while making my first app I noticed that the mouse actions' data used in callbacks doesn't contain the color data of the active point. I tried this for bar plots and scatter plots, when I use clickData for example in a callback, I get its color data when it's numerical but not when it's categorical. The solution here would be to add a field in the JSON data sent to the callback, ideally with the same color.marker name for numerical data to ensure consistency. I thought about making a mapping from my categorical data to a numeric one. The problem with this approach is that it infers a comparison between the categorical values which is not always desirable. Have a great day.

Coding-with-Adam commented 9 months ago

Thank you for this feature request, @Voltini . Can you please share a MRE with the scatter plots you mention?

Voltini commented 9 months ago

Sure, take for example the following code:

from dash import Dash, html, dcc, Input, Output
import plotly.express as px
import numpy as np

app = Dash(__name__)
N = 10
app.layout = html.Div(
    [
        html.Div(
            children=[
                dcc.Graph(
                    figure=px.scatter(
                        x=np.random.random(N),
                        y=np.random.random(N),
                        color=np.random.choice(["a", "b"], N),
                    ),
                    id="plot",
                )
            ],
        ),
        html.Div(id="example", children="Hello World"),
    ],
)

@app.callback(Output("example", "children"), Input("plot", "clickData"))
def call(clickdata):
    return str(clickdata)

if __name__ == "__main__":
    app.run(debug=True)

When I click on a point I get: {'points': [{'curveNumber': 0, 'pointNumber': 3, 'pointIndex': 3, 'x': 0.23940095437991715, 'y': 0.3631388501979541, 'bbox': {'x0': 605.27, 'x1': 611.27, 'y0': 260.14, 'y1': 266.14}}]}

However, if I change the color parameter in my plot to color=np.random.random(N) I get:

{'points': [{'curveNumber': 0, 'pointNumber': 4, 'pointIndex': 4, 'x': 0.11509044553896275, 'y': 0.41656166816663565, 'marker.color': 0.39641498810036235, 'bbox': {'x0': 329.76, 'x1': 335.76, 'y0': 270.62, 'y1': 276.62}}]}

As you can see now I have a marker.color attribute that was not present when my data was categorical.

Edit: Also it seems that the frontend already has access to the desired infromation, I don't know if this comment helps. Screenshot 2024-02-07 113908

Coding-with-Adam commented 9 months ago

Interesting request. Thanks for sharing the code, @Voltini

So, if we had this capability, once we set color=np.random.choice(["a", "b"], N), and you clicked on point 'b', the result you'd expect would be: 'marker.color': 'b' ?

Voltini commented 9 months ago

Hi Adam. Exactly, that's what I was thinking!