plotly 未通过下拉交互正确更新信息

问题描述 投票:0回答:1

plotly
交互时,我面临更新
dropdown
散点图上的中线的问题。下拉列表允许用户选择一列(Y 轴),我希望所选 Y 轴的中位数相应更新。但是,当我从下拉列表中选择一个新变量时,中线不会按预期更新。

我分享一个玩具样本数据:

import pandas as pd

df_input = pd.DataFrame({
    'rows': range(1, 101),
    'column_a': [i + (i % 10) for i in range(1, 101)],
    'column_b': [i * 2 for i in range(1, 101)],
    'column_c': [i ** 0.5 for i in range(1, 101)],
    'outlier_prob': [0.01 * (i % 10) for i in range(1, 101)]
})

这是我使用的功能

import plotly.graph_objects as go

def plot_dq_scatter_dropdown(df):
    # Initialize the figure
    fig = go.Figure()

    # Function to add median lines (vertical for rows, horizontal for selected Y)
    def add_median_lines(y):
        fig.data = []  # Clear previous data

        # Add a scatter trace for the selected Y variable
        fig.add_trace(go.Scatter(
            x=df["rows"],
            y=df[y],
            mode='markers',
            marker=dict(color=df['outlier_prob'], colorscale='viridis', showscale=True, colorbar=dict(title='Outlier Probability')),
            hoverinfo='text',
            text=df.index,  # Or use other columns for hover data if needed
            name=f'{y} vs rows',  # This will still be used for the hover and data display
            showlegend=False  # Hide the legend for each individual trace
        ))

        # Calculate medians for both X and selected Y
        median_x = df["rows"].median()  # Median of X (rows)
        median_y = df[y].median()  # Median of selected Y-variable

        # Add vertical median line for 'rows'
        fig.add_vline(x=median_x, line=dict(color="orange", dash="dash", width=2), 
                      annotation_text="Median rows", annotation_position="top left")

        # Add horizontal median line for selected Y-variable
        fig.add_hline(y=median_y, line=dict(color="orange", dash="dash", width=2), 
                      annotation_text=f"Median {y}, {median_y}", annotation_position="top left")

        # Update layout after adding the data and median lines
        fig.update_layout(
            title=f"Scatter Plot: rows vs {y}",
            xaxis_title="rows",
            yaxis_title=y,
            autosize=True
        )

    # Add a dropdown menu for selecting the Y-axis variable
    fig.update_layout(
        updatemenus=[dict(
            type="dropdown",
            x=0.17,
            y=1.15,
            showactive=True,
            buttons=[
                dict(
                    label=f"{y}",
                    method="update",
                    args=[{
                        'y': [df[y]],
                        'x': [df["rows"]],
                        'type': 'scatter',
                        'mode': 'markers',
                        'marker': dict(color=df['outlier_prob'], colorscale='viridis', showscale=True, colorbar=dict(title='Outlier Probability')),
                        'hoverinfo': 'text',
                        'text': df.index,
                        'name': f'{y} vs rows',
                        'showlegend': False
                    }, {
                        'title': f"Scatter Plot: rows vs {y}",
                        'yaxis.title': y
                    }]
                ) for y in df.columns if y not in ["rows", "outlier_prob"]
            ]
        )]
    )

    # Display the initial plot (default to the second column for the first plot)
    add_median_lines(df.columns[1])

    # Show the plot
    fig.show()

这里是函数调用的例子:

# Call the function to plot the graph
plot_dq_scatter_dropdown(df_input)

这是我在视觉上面临的错误:

column_b selected but horizontal remains as column_a

以绿色勾勒出的水平轨迹出乎意料地恒定为

column_a
,因为我在下拉列表中与之交互的轨迹是
column_b
。垂直轨迹是正确固定的,因为它不与该轴相互作用。

python plotly visualization interactive
1个回答
0
投票

我使用

shapes
参数而不是
add_vline
add_hline
参数修改了函数plot_dq_scatter_dropdown。这是修改后的功能:

def plot_dq_scatter_dropdown(df):
# Initialize the figure
fig = go.Figure()

# Get columns for Y-axis options (excluding 'rows' and 'outlier_prob')
y_columns = [col for col in df.columns if col not in ["rows", "outlier_prob"]]
# Calculate median of rows (constant)
median_x = df["rows"].median()

# Create dropdown buttons with updated configuration
buttons = []
for y_col in y_columns:
    median_y = df[y_col].median()
    button = dict(
        label=y_col,
        method="update",
        args=[
            # Trace updates
            {
                "y": [df[y_col]],  # Update scatter plot Y values
                "x": [df["rows"]],
                "marker.color": [df["outlier_prob"]],
            },
            # Layout updates
            {
                "title": f"Scatter Plot: rows vs {y_col}",
                "yaxis.title": y_col,
                "shapes": [
                    # Vertical median line for rows
                    {
                        "type": "line",
                        "x0": median_x,
                        "x1": median_x,
                        "y0": 0,
                        "y1": 1,
                        "yref": "paper",
                        "line": {"color": "orange", "dash": "dash", "width": 2}
                    },
                    # Horizontal median line for selected Y variable
                    {
                        "type": "line",
                        "x0": 0,
                        "x1": 1,
                        "xref": "paper",
                        "y0": median_y,
                        "y1": median_y,
                        "line": {"color": "orange", "dash": "dash", "width": 2}
                    }
                ],
                "annotations": [
                    # Annotation for vertical median line
                    {
                        "x": median_x,
                        "y": 1,
                        "xref": "x",
                        "yref": "paper",
                        "text": "Median rows",
                        "showarrow": False,
                        "xanchor": "left",
                        "yanchor": "bottom"
                    },
                    # Annotation for horizontal median line
                    {
                        "x": 0,
                        "y": median_y,
                        "xref": "paper",
                        "yref": "y",
                        "text": f"Median {y_col}: {median_y:.2f}",
                        "showarrow": False,
                        "xanchor": "left",
                        "yanchor": "bottom"
                    }
                ]
            }
        ]
    )
    buttons.append(button)

# Add initial scatter plot
initial_y = y_columns[0]
initial_median_y = df[initial_y].median()
fig.add_trace(go.Scatter(
    x=df["rows"],
    y=df[initial_y],
    mode='markers',
    marker=dict(
        color=df['outlier_prob'],
        colorscale='viridis',
        showscale=True,
        colorbar=dict(title='Outlier Probability')
    ),
    hoverinfo='text',
    text=df.index,
    showlegend=False
))

# Update layout with dropdown menu and initial median lines
fig.update_layout(
    title=f"Scatter Plot: rows vs {initial_y}",
    xaxis_title="rows",
    yaxis_title=initial_y,
    updatemenus=[{
        "buttons": buttons,
        "direction": "down",
        "showactive": True,
        "x": 0.17,
        "y": 1.15,
        "type": "dropdown"
    }],
    shapes=[
        # Initial vertical median line
        {
            "type": "line",
            "x0": median_x,
            "x1": median_x,
            "y0": 0,
            "y1": 1,
            "yref": "paper",
            "line": {"color": "orange", "dash": "dash", "width": 2}
        },
        # Initial horizontal median line
        {
            "type": "line",
            "x0": 0,
            "x1": 1,
            "xref": "paper",
            "y0": initial_median_y,
            "y1": initial_median_y,
            "line": {"color": "orange", "dash": "dash", "width": 2}
        }
    ],
    annotations=[
        # Initial annotation for vertical median line
        {
            "x": median_x,
            "y": 1,
            "xref": "x",
            "yref": "paper",
            "text": "Median rows",
            "showarrow": False,
            "xanchor": "left",
            "yanchor": "bottom"
        },
        # Initial annotation for horizontal median line
        {
            "x": 0,
            "y": initial_median_y,
            "xref": "paper",
            "yref": "y",
            "text": f"Median {initial_y}: {initial_median_y:.2f}",
            "showarrow": False,
            "xanchor": "left",
            "yanchor": "bottom"
        }
    ]
)

# Show the plot
fig.show()

这应该计算每列的中值并将它们包含在按钮配置中。它还相应地注释了这些行。我附上一些结果输出的图像enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.