如何根据下拉列表更新所选标记​​的颜色?

发布于 2025-02-06 19:44:30 字数 3386 浏览 2 评论 0原文

我有多个集群,群集中的每个数据点都有一个特殊的组。我试图根据选定值(组)从下拉列表中突出显示所选的数据点(带有黄色)。

代码:

import pandas as pd
import numpy as np

def generate_random_cluster(name, size, loc_x, loc_y, groups=['A','B','C'], p=None):
    
    return pd.DataFrame({
        'name': name,
        'x': np.random.normal(loc=loc_x, size=size),
        'y': np.random.normal(loc=loc_y, size=size),
        'group': np.random.choice(['A','B','C'], size=size, p=p)
    })

groups = ['A','B','C']

cluster_1 = generate_random_cluster(name='cluster_1', size=15, loc_x=3, loc_y=2, groups=groups, p=[0.7, 0.2, 0.1])
cluster_2 = generate_random_cluster(name='cluster_2', size=35, loc_x=9, loc_y=5, groups=groups, p=[0.2, 0.7, 0.1])
cluster_3 = generate_random_cluster(name='cluster_3', size=20, loc_x=6, loc_y=8, groups=groups, p=[0.1, 0.2, 0.7])

data = pd.concat([cluster_1, cluster_2, cluster_3]).reset_index(drop=True)
data.head()

返回这样的数据

名称xy
cluster_13.1980480.385736b
cluster_11.7840802.608631
cluster_1一个文档a
示例数据生成
4.1601032.119545框架

从 我以为我只需要使用update_layout这样的方法:

import plotly.graph_objects as go

cluster_colors = {'cluster_1': 'green', 'cluster_2': 'red', 'cluster_3': 'blue'}

layout = go.Layout(
    xaxis = go.layout.XAxis(
        showticklabels=False),
    yaxis = go.layout.YAxis(
         showticklabels=False
    )
)

fig = go.Figure(layout=layout)

for cluster_ix, (cluster, df) in enumerate(data.groupby('name')):
    
    customdata = df['group']
    
    fig.add_scatter(
        x=df['x'],
        y=df['y'],
        name=cluster,
        mode='markers',
        customdata=customdata,
        hovertemplate="<br>".join([
            "X: %{x}",
            "Y: %{y}",
            "Group: %{customdata}"
        ]),
        marker_color=[cluster_colors[cluster] for _ in range(len(df))],
    )

def highlight_group(group):    
    result = []
    
    for tracer_ix, tracer in enumerate(fig["data"]):
        colors = ["yellow" if datapoint_group == group else cluster_colors[fig["data"][tracer_ix]["name"]] for datapoint_group in fig["data"][tracer_ix]["customdata"]]
        result.append(colors)
    
    return result
    
fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker": {"color": highlight_group(group)}}
                    ],
                }
                for group in groups
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

fig.show()

这会生成这样的图:

“散点图”

但是当我从下拉列表中更改值时,每个标记都会变黑:

如何正确突出选定的标记?

I have multiple clusters and each datapoint in the cluster has a special group. I am trying to highlight selected data points (with yellow color) in the plotly scatter plot based on selected value (group) from a dropdown list.

Here is a code to generate sample data:

import pandas as pd
import numpy as np

def generate_random_cluster(name, size, loc_x, loc_y, groups=['A','B','C'], p=None):
    
    return pd.DataFrame({
        'name': name,
        'x': np.random.normal(loc=loc_x, size=size),
        'y': np.random.normal(loc=loc_y, size=size),
        'group': np.random.choice(['A','B','C'], size=size, p=p)
    })

groups = ['A','B','C']

cluster_1 = generate_random_cluster(name='cluster_1', size=15, loc_x=3, loc_y=2, groups=groups, p=[0.7, 0.2, 0.1])
cluster_2 = generate_random_cluster(name='cluster_2', size=35, loc_x=9, loc_y=5, groups=groups, p=[0.2, 0.7, 0.1])
cluster_3 = generate_random_cluster(name='cluster_3', size=20, loc_x=6, loc_y=8, groups=groups, p=[0.1, 0.2, 0.7])

data = pd.concat([cluster_1, cluster_2, cluster_3]).reset_index(drop=True)
data.head()

Which returns dataframe like this:

namexygroup
cluster_13.1980480.385736B
cluster_11.7840802.608631A
cluster_14.1601032.119545A
cluster_12.5224861.994962B
cluster_14.0730541.204167A

I am quite new to plotly, but based from documentation I thought I just need to use update_layout method like this:

import plotly.graph_objects as go

cluster_colors = {'cluster_1': 'green', 'cluster_2': 'red', 'cluster_3': 'blue'}

layout = go.Layout(
    xaxis = go.layout.XAxis(
        showticklabels=False),
    yaxis = go.layout.YAxis(
         showticklabels=False
    )
)

fig = go.Figure(layout=layout)

for cluster_ix, (cluster, df) in enumerate(data.groupby('name')):
    
    customdata = df['group']
    
    fig.add_scatter(
        x=df['x'],
        y=df['y'],
        name=cluster,
        mode='markers',
        customdata=customdata,
        hovertemplate="<br>".join([
            "X: %{x}",
            "Y: %{y}",
            "Group: %{customdata}"
        ]),
        marker_color=[cluster_colors[cluster] for _ in range(len(df))],
    )

def highlight_group(group):    
    result = []
    
    for tracer_ix, tracer in enumerate(fig["data"]):
        colors = ["yellow" if datapoint_group == group else cluster_colors[fig["data"][tracer_ix]["name"]] for datapoint_group in fig["data"][tracer_ix]["customdata"]]
        result.append(colors)
    
    return result
    
fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker": {"color": highlight_group(group)}}
                    ],
                }
                for group in groups
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

fig.show()

This generates plot like this:

Scatter plot

But when I change the value from the dropdown list, every marker turns black:

Scatter plot - error

How to correctly highlight selected markers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

弃爱 2025-02-13 19:44:30

基于 @jmmease的答案在这里情节论坛,我相信您可以重组标记字典:

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker.color": highlight_group(group)}
                    ],
                }
                for group in groups
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

这是结果:

“在此处输入映像”

这完成了您在原始问题中所要求的内容,但是从设计角度来看,您可能需要添加另一个下拉列表选项,所以您可以选择不选择组 - 否则,一旦选择了一个组,就无法将数字返回其原始状态。

由于您的代码非常强大,因此您可以通过groups+[“ none”]来创建按钮而不是组(因此我不修改groups),您标签none

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker.color": highlight_group(group)}
                    ],
                }
                for group in groups+["None"]
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

然后,结果看起来像这样:

下一部分超出了您原始问题的范围,但是传说中可能会有一些潜在的混乱,因为当您创建图形时,每个群集的名称(因此如图所示的标记颜色)在传说中)链接到群集而不是标记颜色 - 这意味着,当您选择某个特定组以彩色“黄色”时,您将拥有一个群集组,其中一些标记为黄色,而其他标记则具有其原始标记颜色,我相信Plotly将必须任意选择颜色为传说 - 可能是组中第一个标记的颜色。

例如,一旦我们从下拉列表中选择组Bcluster 3主要是蓝色标记,如您在创建图时所定义的那样,但是也有来自黄色标记的混合物B组,这导致传奇条目为黄色。对于cluster 2,存在相同的问题,该问题主要是红色标记,但包含一些B组黄色标记。如果我想到解决方案,我将更新答案。

Based on @jmmease's answer here in the plotly forums, I believe you can restructure the markers dictionary:

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker.color": highlight_group(group)}
                    ],
                }
                for group in groups
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

Here is the result:

enter image description here

This accomplishes what you asked in your original question, but from a design perspective, you might want to add another dropdown option so that you can select no groups – otherwise, once you select a group, you cannot return the figure to its original state.

Since your code is pretty robust, you can iterate through groups+["None"] to create the buttons instead of groups (so that I don't modify groups), you will have another dropdown option with the label None:

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": group,
                    "method": "update",
                    "args": [
                        {"marker.color": highlight_group(group)}
                    ],
                }
                for group in groups+["None"]
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
    height=700
)

Then the result looks like this:
enter image description here

This next part is beyond the scope of your original question, but there may be some potential confusion in the legend because when you create the figure, the name of each cluster (and therefore the marker color as indicated in the legend) is linked to the cluster instead of the marker color – this means that when you select a certain group to color "yellow", you'll have a cluster group where some markers are colored yellow, and other markers have their original color, and I believe plotly will have to choose a color arbitrarily for the legend – probably the color of the first marker within a group.

For example, once we select Group B from the dropdown, cluster 3 is mostly blue markers as you defined when creating the figure, but there is also a mixture of yellow markers from Group B, and this causes the legend entry to be colored yellow. The same issue exists for cluster 2 which is mostly red markers but contains some Group B yellow markers. If I think of a solution, I'll update my answer.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文