You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dash交互式拳击手数据仪表盘开发报错排查求助

解决Dash拳击手仪表盘的两个错误

我来帮你搞定这两个问题,咱们逐个拆解分析:


1. Dropdown的options[14].label缺失警告

这个问题的核心是你的division字段里存在空值(NaN)或者空字符串,导致生成Dropdown选项时,某个选项的label和value无效(比如是NaN),而Dash要求每个Dropdown选项必须具备有效的字符串类型label和value。

修复方案:

生成选项前先过滤掉division里的空值和无效值,把原来的代码:

options=[{'label': i, 'value': i} for i in data['division'].unique()]

替换为:

# 先过滤掉NaN,再排除空字符串(如果数据里存在的话)
valid_divisions = data['division'].dropna().unique()
valid_divisions = [d for d in valid_divisions if str(d).strip() != '']
options=[{'label': i, 'value': i} for i in valid_divisions]

同时,全局的WEIGHT_CLASS变量也要同步更新,避免回调逻辑里用到无效值:

WEIGHT_CLASS = data['division'].dropna().unique()
WEIGHT_CLASS = [d for d in WEIGHT_CLASS if str(d).strip() != '']

2. 回调里的YAxis无效属性错误

你在layout的yaxis里写的{'1': 40, 'b': '40', 't': 10, 'r': 10}完全是错误的参数——这些不是Plotly YAxis的合法属性。看起来你可能是想设置图表边距或者Y轴数值范围?

修复方案:

  • 如果是想设置Y轴的数值范围,用range参数,比如range=[0, 50](可根据你的数据动态调整)
  • 如果是想设置图表的边距,要把margin单独放在layout根节点下,而不是嵌套在yaxis中

把原来的layout部分改成:

'layout': go.Layout(
    xaxis={'title': 'Bouts fought'},
    yaxis={'title': 'Wins', 'range': [0, max(weight_df['w']) + 5]},  # 设置Y轴标题和动态范围
    margin={'l': 40, 'b': 40, 't': 10, 'r': 10},  # 正确设置图表边距
    legend={'x': 0, 'y': 1},
    hovermode='closest'
)

这样就完全符合Plotly的布局规范,不会再触发ValueError了。


完整修正后的代码

把以上修改整合后的完整可运行代码如下:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd

# 用你提供的样例数据初始化DataFrame
data = pd.DataFrame({
    'name': {0: 'Roberto Salas', 3: 'James Jackson', 6: 'Alex Love', 9: 'Juan Centeno', 12: 'Jordan Weeks'},
    'division': {0: 'cruiser', 3: 'heavy', 6: 'bantam', 9: 'fly', 12: 'super middle'},
    'w': {0: 5.0, 3: 4.0, 6: 3.0, 9: 4.0, 12: 2.0},
    'l': {0: 0.0, 3: 0.0, 6: 0.0, 9: 3.0, 12: 0.0},
    'd': {0: 0.0, 3: 1.0, 6: 0.0, 9: 1.0, 12: 0.0},
    'location': {0: 'USA', 3: 'USA', 6: 'USA', 9: 'USA', 12: 'USA'},
    'from': {0: 2016.0, 3: 2017.0, 6: 2018.0, 9: 2016.0, 12: 2019.0},
    'sex': {0: 'male', 3: 'male', 6: 'female', 9: 'male', 12: 'male'}
})

# 计算参赛场次
data['bouts_fought'] = data['w'].astype('float') + data['l'].astype('float') + data['d'].astype('float')

# 过滤有效量级,排除空值和空字符串
WEIGHT_CLASS = data['division'].dropna().unique()
WEIGHT_CLASS = [d for d in WEIGHT_CLASS if str(d).strip() != '']

app = dash.Dash()
app.css.append_css({ "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css" })

# 页面布局
app.layout = html.Div(children=[
    html.H1(children='Visualizing boxer stats', style={ 'textAlign': 'center', }),
    dcc.Dropdown(
        id='weight_class',
        options=[{'label': i, 'value': i} for i in WEIGHT_CLASS],
        multi=True,
        placeholder="Select weight divisions"  # 可选:添加占位提示提升体验
    ),
    dcc.Graph(
        id='total-bouts-v-bouts-won',
    )
])

@app.callback(
    Output('total-bouts-v-bouts-won', 'figure'),
    [Input('weight_class', 'value')])
def update_scatterplot(weight_class):
    if weight_class is None or weight_class == []:
        weight_class = WEIGHT_CLASS
    weight_df = data[(data['division'].isin(weight_class))]
    
    # 动态计算Y轴范围,避免数据超出显示范围
    y_max = weight_df['w'].max() if not weight_df.empty else 10
    y_range = [0, y_max + 5]
    
    return {
        'data': [
            go.Scatter(
                x=weight_df['bouts_fought'],
                y=weight_df['w'],
                text=weight_df['name'],
                mode='markers',
                opacity=0.5,
                marker={
                    'size': 14,
                    'line': {'width': 0.5, 'color': 'blue'}
                },
            )
        ],
        'layout': go.Layout(
            xaxis={'title': 'Bouts fought'},
            yaxis={'title': 'Wins', 'range': y_range},
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
        )
    }

if __name__ == '__main__':
    app.run_server(debug=True)

额外优化说明

  • 给Dropdown添加了placeholder提示,提升用户交互体验
  • Y轴范围改成动态计算,根据选中数据的最大获胜场次自动调整,避免图表显示不全
  • 全程过滤空值,避免后续出现其他潜在的数据异常问题

内容的提问来源于stack exchange,提问作者Emm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:45:20