基于Jupyter ipywidgets实现三级联动下拉并存入Pandas DataFrame
实现三级联动运动选择下拉菜单并将结果存入Pandas DataFrame
问题背景
需要在Jupyter Notebook中使用ipywidgets的交互功能,从三层嵌套字典中选择运动内容。字典按身体部位→基础动作→动作变体分层,示例结构如下:
my_exercise_dic={ 'Core':{'Plank':['Plank','Side Plank','Weighted Plank'],'Deadbug':['Deadbug','Weighted Deadbug']}, 'Upper Body':{'Pull Ups':['Pull Ups','Chin Ups','Wide Pull Ups'],'Push Ups':['Push Ups','Clapping Push Ups']} }
目标是创建三级联动下拉菜单,依次选择后返回最终的动作变体,并将结果存入Pandas DataFrame。
初始繁琐实现
最初通过分单元格运行代码实现,但操作步骤繁琐:
第一步:创建身体部位选择器
from ipywidgets import interactive from IPython.display import display def f(select): return select x=interactive(f, body_part=my_exercise_dic.keys()) display(x)
第二步:根据选中部位创建基础动作选择器
def g(select): return select y = interactive(g, pattern=my_exercise_dic[x.result].keys()) display(y)
第三步:根据选中动作创建变体选择器
def e(select): return select z= interactive(e, exercise=my_exercise_dic[x.result][y.result]) display(z)
通过z.result获取最终选中的动作变体。
优化后的联动下拉+DataFrame存储实现
将流程优化为自动联动的连续功能,同时实现选中结果一键存入DataFrame:
import ipywidgets as widgets from IPython.display import display import pandas as pd # 定义完整的运动选项 option1 = ['Core', 'Lower Push', 'Lower Pull', 'Upper Push', 'Upper Pull'] option2 = {'Core': ['Plank', 'Deadbug', 'Ab Wheel', 'Leg Raise', 'Tuck'], 'Lower Push': ['Squat', 'Step Up', 'Lunge', 'Split Squat', 'Leg Extension', 'Sled', 'Jump'], 'Lower Pull': ['Deadlift', 'Swings', 'Bridge', 'Leg Curl', 'Clean', 'Snatch'], 'Upper Push': ['Bench Press', 'Push Ups', 'Floor Press', 'Chest Fly', 'Raise', 'OHP', 'Tricep'], 'Upper Pull': ['Pull Up', 'Lat Pull Down', 'Row', 'Shrug', 'Reverse Fly', 'Prone Raise', 'Band Pull', 'Pull Over', 'Curl']} option3 = {'Plank': ['Plank', 'Side Plank', 'Push Up to Plank', 'Saw Plank', 'Side with Vert Row Plank'], 'Deadbug': ['Deadbug', 'Heel Tap Deadbug', 'Lateral Hold Deadbug'], 'Ab Wheel': ['Ab Wheel', 'Cart Ab Wheel', 'TRX Ab Wheel'], 'Leg Raise': ['Leg Raise', 'Arcing Leg Raise', 'Eccentric Leg Raise', 'V-Up Leg Raise', 'Hanging Leg Raise', 'Hanging Knee Raise Leg Raise'], 'Tuck': ['Tuck', 'Pike Tuck'], 'Squat': ['Squat', 'Box Squat', 'Front Squat', 'Front Box Squat', 'High Bar Squat', 'Low Bar Squat', 'Pause Squat', 'Pause Front Squat', 'Goblet Squat', 'Jump Squat', 'Zercher Squat', 'Sumo Squat', 'Single Leg Box Squat'], 'Step Up': ['Step Up', 'Knee Drive Step Up', 'Lateral Step Up', 'Explosive Step Up'], 'Lunge': ['Lunge', 'Reverse Lunge', 'Walking Lunge', 'With Knee Drive Lunge', 'Post Lunge', 'Forward Lunge', 'Elevated Reverse Lunge', 'Explosive Lunge', 'Lateral Lunge Lunge'], 'Split Squat': ['Split Squat', 'Bulgarian Split Squat', 'Front Foot Elevated Split Squat'], 'Leg Extension': ['Leg Extension', 'Single Leg Leg Extension'], 'Sled': ['Sled', 'Push Sled', 'Drag Sled', 'Backwards Drag Sled', 'Rope Drag Sled'], 'Jump': ['Jump', 'Box Jump', 'Depth Jump', 'Broad Jump', 'Single Leg Box Jump'], 'Deadlift': ['Deadlift', 'Romanian Deadlift', 'Stiff Leg Deadlift', 'Split Stance Romainian Deadlift', 'Single Leg Deadlift', 'Sumo Deadlift', 'Pause Deadlift'], 'Swings': ['Swings', 'Single Arm Swings'], 'Bridge': ['Bridge', 'Bench Bridge', 'Single Leg Bridge'], 'Leg Curl': ['Leg Curl', 'Machine Leg Curl', 'Cart Leg Curl'], 'Clean': ['Clean', 'Single Clean', 'Double Clean'], 'Snatch': ['Snatch', 'Single Snatch', 'Double Snatch'], 'Bench Press': ['Bench Press', 'Incline Bench Press', 'Incline Close Grip Bench Press', 'Incline Neutral Grip Bench Press', 'Close Grip Bench Press', 'Neutral Grip Bench Press', 'Pause Bench Press', 'Incline Pause Bench Press', 'Neutral Pause Bench Press', 'Wide Grip Bench Press', 'Wide Pause Bench Press', 'Pin Bench Press'], 'Push Ups': ['Push Ups', 'Incline Push Ups', 'Decline Push Ups', 'Hand Release Push Ups', 'Explosive Push Ups'], 'Floor Press': ['Floor Press', 'Neutral Grip Floor Press', 'Close Grip Floor Press', 'Alternating Floor Press'], 'Chest Fly': ['Chest Fly', 'Decline Chest Fly', 'Incline Chest Fly'], 'Raise': ['Raise', 'Lateral Raise', 'Front Raise', 'Front to Lateral Raise'], 'OHP': ['OHP', 'Seated OHP', 'Kneeling OHP', 'Kneeling Lunge OHP', 'Push Press OHP', 'Jerk OHP', 'Single Arm OHP', 'Single Arm Kneeling OHP', 'Single Arm Kneeling Lunge OHP', 'Single Arm Push Press OHP', 'Viking OHP', 'Single Arm Viking OHP'], 'Tricep': ['Tricep', 'Overhead Extension Tricep', 'Skull Crusher Tricep', 'Rope Pull Down Tricep', 'Bar Pull Down Tricep', 'Reverse Grp Pull Down Tricep', 'Single Arm Pull Down Tricep', 'Reverse Grip Single Arm Pull Down Tricep'], 'Pull Up': ['Pull Up', 'Chin Pull Up', 'Neutral Grip Pull Up', 'Wide Pull Up', 'Negative Pull Up', 'Assisted Pull Up'], 'Lat Pull Down': ['Lat Pull Down', 'Wide Lat Pull Down', 'Neutral Grip Lat Pull Down', 'Chin Lat Pull Down', 'Single Arm Lat Pull Down', 'Dual Wide Lat Pull Down'], 'Row': ['Row', 'Bench Row', 'Bench with Pause Row', 'Chest Supported Row', 'Chest Supported with Pause Row', 'Renegade Row', 'Seated Cable Row', 'Bent Over Row', 'Inverted Row', 'Inverted with Pause Row'], 'Shrug': ['Shrug', 'Shrug with Pause Shrug'], 'Reverse Fly': ['Reverse Fly', 'on bench Reverse Fly'], 'Prone Raise': ['Prone Raise', 'Cactus Press Prone Raise', "T's Prone Raise", "Y's Prone Raise", "I's Prone Raise"], 'Band Pull': ['Band Pull', 'Apart Band Pull', "W's Band Pull"], 'Pull Over': ['Pull Over', 'Incline Pull Over', 'Medball Pull Over'], 'Curl': ['Curl', 'Hammer Curl', 'Rotational Curl', 'EZ Curl']} # 初始化存储结果的DataFrame exercise_df = pd.DataFrame(columns=['身体部位', '基础动作', '动作变体']) # 创建下拉菜单 dropdown1 = widgets.Dropdown(options=option1, description='身体部位:') dropdown2 = widgets.Dropdown(options=option2[dropdown1.value], description='基础动作:') dropdown3 = widgets.Dropdown(options=option3[dropdown2.value], description='动作变体:') # 定义下拉菜单联动逻辑 def update_dropdown2(*args): dropdown2.options = option2[dropdown1.value] dropdown2.value = dropdown2.options[0] def update_dropdown3(*args): dropdown3.options = option3[dropdown2.value] dropdown3.value = dropdown3.options[0] dropdown1.observe(update_dropdown2, 'value') dropdown2.observe(update_dropdown3, 'value') # 定义添加到DataFrame的函数 def add_to_df(b): global exercise_df new_row = pd.DataFrame({ '身体部位': [dropdown1.value], '基础动作': [dropdown2.value], '动作变体': [dropdown3.value] }) exercise_df = pd.concat([exercise_df, new_row], ignore_index=True) print("已添加到DataFrame:") display(exercise_df) # 创建添加按钮 add_button = widgets.Button(description='添加到训练计划') add_button.on_click(add_to_df) # 显示控件 display(dropdown1, dropdown2, dropdown3, add_button)
功能说明
- 联动下拉:选择身体部位后,基础动作下拉菜单自动更新为对应选项;选择基础动作后,动作变体菜单自动更新。
- 添加到DataFrame:点击「添加到训练计划」按钮,当前选中的三级选项会作为一行添加到
exercise_df中,同时打印并显示更新后的DataFrame。 - 数据持久化:每次添加都会保留之前的记录,可直接对
exercise_df进行后续分析或导出操作。
内容的提问来源于stack exchange,提问作者pedro flores
相关产品推荐
相关产品推荐

