python - 单击几下后“update_layout”无法正常工作

标签 python python-3.x drop-down-menu plotly plotly-python

我有一个下拉菜单,我可以在其中为散点图选择 x 轴和 y 轴变量。此外,可以在菜单中选择一个分类变量,指示如何为点着色。这似乎适用于几次点击,但随后我在悬停框中得到了 '%{customdata[0]}',而且 plotly 不正确。我在 JupyterLab3 中使用 plotly 5.9.0。为了能够为着色选择分类变量,我使用了轨迹。下面是一个可重现的例子:

import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go

X = pd.DataFrame({  'num1': [1,2,3,4],
                    'num2': [40,30,20,10],
                    'num3': [0,1,2,3],
                    'cat1': ['A', 'A', 'A', 'B'],
                    'cat2': ['c', 's', 's', 's'],
                    'cat3': ['a', 'b', 'c', 'd']})

numerical_features   = sorted(X.select_dtypes(include=np.number).columns.tolist())
categorical_features = sorted(list(set(X.columns) - set(numerical_features)))

feature_1 = numerical_features[0]
feature_2 = numerical_features[1]

fig = go.Figure()

for categorical_feature_id in range(len(categorical_features)):

    fig.add_traces(list(px.scatter(X, x=feature_1, y=feature_2, color=categorical_features[categorical_feature_id],
                                         labels={feature_1:feature_1, feature_2:feature_2},
                                         hover_data=['cat3', 'num3']).select_traces()))

fig.update_layout(
        xaxis_title=feature_1,
        yaxis_title=feature_2,
        updatemenus=[
            {
                "buttons": [
                    {
                        "label": f"x - {x}",
                        "method": "update",
                        "args": [
                            {"x": [X[x]]},
                            {"xaxis": {"title": x}},
                        ],
                    }
                    for x in numerical_features
                ]
            },
            {
                "buttons": [
                    {
                        "label": f"y - {y}",
                        "method": "update",
                        "args": [
                            {"y": [X[y]]},
                            {"yaxis": {"title": y}}
                        ],
                    }
                    for y in numerical_features
                ],
                "y": 0.8,
            },
            {
                "buttons": [
                    {
                        "label": f"z - {categorical_features[categorical_feature_id]}",
                        "method": "update",
                        "args": [{'visible':    [False if (i<categorical_feature_id) or (i>categorical_feature_id) else True for i in range(len(categorical_features))]},
                                 {'showlegend': [False if (i<categorical_feature_id) or (i>categorical_feature_id) else True for i in range(len(categorical_features))]}]
                    }
                    for categorical_feature_id in range(len(categorical_features))
                ],
                "y": 0.6,
            }])
fig.show()

An example of how the figure looks after a few updates

已针对 R 讨论了类似的问题:

Dropdown menu for changing the color attribute of data in scatter plot (Plotly R)

如有任何帮助,我将不胜感激。

最佳答案

您好,我稍微更新了您的代码。

我认为这里必须进行数据转换。

我用 go.Scatter() 切换了 px.scatter 现在悬停框似乎可以工作了。

我希望这能解决问题。

import pandas as pd
import numpy as np
import seaborn as sns
import plotly.graph_objects as go
from collections import defaultdict

X = pd.DataFrame({  'num1': [1,2,3,4],
                    'num2': [40,30,20,10],
                    'num3': [0,1,2,3],
                    'cat1': ['A', 'A', 'A', 'B'],
                    'cat2': ['c', 's', 's', 's'],
                    'cat3': ['a', 'b', 'c', 'd']})

numerical_features   = sorted(X.select_dtypes(include=np.number).columns.tolist())
categorical_features = sorted(list(set(X.columns) - set(numerical_features)))

dfs_list = []

for categorical_feature in categorical_features:
    features = numerical_features.copy()
    features.append(categorical_feature)
    dfs_list.append(X[features].copy())

unique_classes = list(pd.unique(X[categorical_features].values.ravel()))
dict_cat_color = {unique_classes[i] : 'rgb' + str(sns.color_palette(n_colors=len(unique_classes))[i])
                  for i in range(len(unique_classes))}

features_w_cat = numerical_features.copy()
features_w_cat.append('cat')

for x in dfs_list:
    x.columns  = features_w_cat
    x["color"] = x.cat.map(dict_cat_color)

orDict = defaultdict(list)

fig = go.Figure()

# Workaround for the legend: Adding empty scatter plots with customized color and text

for key in dict_cat_color.keys():

    fig.add_traces(go.Scatter(
        x             = [None],
        y             = [None],
        name          = key,
        marker_color  = dict_cat_color[key],
        mode          = "markers",
        showlegend    = True
    ))
    
    for categorical_feature in categorical_features:
        
        if key in X[categorical_feature].unique():
            orDict[categorical_feature].append(True)
        else:
            orDict[categorical_feature].append(False)

for index,df in enumerate(dfs_list):
    
    fig.add_traces(go.Scatter(
        x             = [None],
        y             = [None],
        marker_color  = df["color"],
        customdata    = df.loc[:, ["num1","num2","num3","cat"]],
        mode          = "markers",
        hovertemplate = 'num1=%{customdata[0]}<br>num2=%{customdata[1]}<br>num3=%{customdata[2]}<br>cat=%{customdata[3]}',
        showlegend    = False
    ))

fig.update_layout(
        xaxis_title = '',
        yaxis_title = '',
        updatemenus = [
            {
                "buttons": [
                    {
                        "label": f"x - {x}",
                        "method": "update",
                        "args": [
                            {"x": [X[x]]},
                            {"xaxis": {"title": x}},
                        ],
                    }
                    for x in numerical_features
                ]
            },
            {
                "buttons": [
                    {
                        "label": f"y - {y}",
                        "method": "update",
                        "args": [
                            {"y": [X[y]]},
                            {"yaxis": {"title": y}}
                        ],
                    }
                    for y in numerical_features
                ],
                "y": 0.8,
            },
            {
                "buttons": [
                    {
                        "label": f"z - {categorical_features[categorical_feature_id]}",
                        "method": "update",
                        "args": [{'visible': orDict[categorical_features[categorical_feature_id]] + [False if (i<categorical_feature_id) or (i>categorical_feature_id) else True for i in range(len(categorical_features))]}],
                    }
                    for categorical_feature_id in range(len(categorical_features))
                ],
                "y": 0.6,
            }])

fig.show()

关于python - 单击几下后“update_layout”无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72911635/

相关文章:

php - Codeigniter form_dropdown错误

python - 来自 Python 项目的 RPM 子包

python - 计算外键关系中出现的次数

if-statement - 多行相关下拉菜单

python - 理解这个递归

python - 如何将python应用程序连接到在线数据库

javascript - 尝试检查负载上的下拉值,但它不起作用。

python - Fastai - 在句子处理器,cache_dir 参数中启动语言模型失败

python - 使用 Python ftplib 的远程 FTP 服务器中文件的 MD5 值

python - 如何在Python中将多级别的API响应转换为数据帧