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

Jupyter中交互式过滤后KDE动画绘图问题求助

我来帮你修复这个问题,让你的KDE动画能响应ipywidgets的过滤变化,并且按月正确切换。咱们先看修正后的完整代码,再拆解每一处的改进:


修正后的完整代码

import ipywidgets as widgets
from ipywidgets import interact_manual
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import animation, rc
from IPython.display import HTML
import pandas as pd

# 假设你的widgets已经提前定义好(比如下面的示例,根据你的实际数据调整)
# channel_widget = widgets.SelectMultiple(options=df['SALES CHANNEL'].unique(), description='Channel')
# currency_widget = widgets.Dropdown(options=df['CURRENCY'].unique(), description='Currency')
# cumulative_widget = widgets.Checkbox(value=False, description='Use Cumulative')

# 全局设置动画渲染模式,确保在Notebook中正常显示
rc('animation', html='jshtml')

def create_kde_animation(channel, currency, use_cumulative):
    # 1. 先获取最新的过滤后数据
    filtered_df = df[(df['SALES CHANNEL'].isin(channel)) & (df['CURRENCY'] == currency)]
    
    # 2. 初始化绘图画布
    fig, ax = plt.subplots()
    ax.set_xlim(0, 17500)
    ax.set_xlabel('Price')
    ax.set_ylabel('Density')
    
    # 修正月份拼写错误(原代码的"Novemer"改为"November")
    month_list = ['', 'January', 'February', 'March', 'April', 'May', 'June', 
                  'July', 'August', 'September', 'October', 'November', 'December']
    
    def init():
        # 初始化时清空轴,避免残留旧图形
        ax.cla()
        ax.set_xlim(0, 17500)
        ax.set_xlabel('Price')
        ax.set_ylabel('Density')
        return ax,
    
    def animate(i):
        # i代表当前月份(1-12,匹配你的MONTH列数值类型)
        current_month = i
        # 筛选当月的过滤后数据
        monthly_data = filtered_df[filtered_df['MONTH'] == current_month]
        
        ax.cla()
        ax.set_xlim(0, 17500)
        ax.set_xlabel('Price')
        ax.set_ylabel('Density')
        ax.set_title(f'Price Density {month_list[current_month]}')
        
        if not monthly_data.empty:
            # 计算两组KDE所需数据:家族平均价格、所有单品价格
            family_avg_price = monthly_data.groupby('FAMILY')[' PRICE/UNIT (EGP) '].mean()
            all_unit_prices = monthly_data[' PRICE/UNIT (EGP) ']
            
            # 绘制两条KDE曲线,添加图例区分
            sns.kdeplot(family_avg_price, ax=ax, label='Family Avg Price', cumulative=use_cumulative)
            sns.kdeplot(all_unit_prices, ax=ax, label='All Unit Prices', cumulative=use_cumulative)
            ax.legend()
        else:
            # 当月无数据时显示提示
            ax.text(0.5, 0.5, 'No Data Available', ha='center', va='center', transform=ax.transAxes)
        
        return ax,
    
    # 创建动画:frames设置为1-12(对应12个月份),interval是切换间隔(毫秒)
    anim = animation.FuncAnimation(fig, animate, init_func=init, 
                                   frames=range(1, 13), interval=1000, blit=True)
    
    # 关闭静态画布,避免额外显示空图
    plt.close(fig)
    
    # 返回动画的HTML对象,让Notebook渲染显示
    return HTML(anim.to_jshtml())

# 绑定过滤组件与动画生成函数,每次点击Run都会更新动画
interact_manual(create_kde_animation, 
                channel=channel_widget, 
                currency=currency_widget, 
                use_cumulative=cumulative_widget)

关键改进点说明

  1. 绑定过滤与动画更新
    把动画生成逻辑放到了create_kde_animation函数中,并用interact_manual和你的过滤widget绑定。现在每次调整过滤条件并点击Run,都会重新执行数据过滤并生成最新的动画,彻底解决了原代码不响应过滤变化的问题。

  2. 动态获取月度数据
    在animate函数里,每次根据当前帧i(代表月份)重新筛选当月的过滤后数据,而不是在初始化时就固定死数据,这样动画每切换一个月,都会用对应月份的最新过滤数据绘制KDE。

  3. 完善绘图逻辑

    • 每次绘制前用ax.cla()清空轴,避免旧曲线残留;
    • 重新设置坐标轴范围、标签和标题,保证每个月份的图都有正确的显示;
    • 添加了空数据判断,如果当月没有符合条件的数据,会显示友好提示,避免报错。
  4. 响应use_cumulative参数
    在sns.kdeplot中加入了cumulative=use_cumulative参数,现在勾选"Use Cumulative"后,会自动切换为累积分布的KDE曲线。

  5. 细节修复

    • 修正了月份列表里的拼写错误("Novemer"→"November");
    • 用plt.close(fig)关闭静态画布,避免Notebook里额外显示空图;
    • 添加了图例,方便区分两条KDE曲线的含义。

小提醒

如果你的df['MONTH']列存储的是字符串(比如"Jan"),需要把frames和筛选逻辑改成对应字符串的范围,比如frames=['Jan','Feb',...,'Dec'],并调整monthly_data = filtered_df[filtered_df['MONTH'] == current_month]的匹配逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:38