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

VS Code中Jupyter Notebook高效处理千余需用户输入的绘图

解决方案

1. 在Jupyter Notebook中高效管理超500张图表

Jupyter输出中断的核心原因是未清理的图表占据大量内存,以及默认输出缓冲区限制。可以通过以下方法解决:

(1)实时清理图表内存

每次显示图表后手动关闭当前图表对象,释放内存,避免内存堆积。修改后的绘图代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 常量定义
ID_COLUMN = 'ID'
Z_COLUMN = 'Z'
X_COLUMN = 'X'
Y_COLUMN = 'Y'

# 示例数据
data = pd.DataFrame({
    ID_COLUMN: np.random.choice(['A', 'B', 'C'], 1000),
    Z_COLUMN: np.random.choice([10, 20, 30], 1000),
    X_COLUMN: np.random.rand(1000) * 100,
    Y_COLUMN: np.random.rand(1000) * 50
})

def plot_data(data):
    unique_ids = data[ID_COLUMN].unique()
    # 记录已处理项,用于中断后恢复
    processed = []
    # 加载已处理记录(如果存在)
    try:
        processed_df = pd.read_csv('processed_records.csv')
        processed = list(zip(processed_df['ID'], processed_df['Z']))
    except FileNotFoundError:
        pass
    
    for data_id in unique_ids:
        filtered_data = data[data[ID_COLUMN] == data_id]
        unique_z_values = filtered_data[Z_COLUMN].unique()
        
        for z_value in unique_z_values:
            if (data_id, z_value) in processed:
                continue
                
            filtered_data_z = filtered_data[filtered_data[Z_COLUMN] == z_value]
            
            # 创建图表对象并赋值,方便后续关闭
            fig = plt.figure()
            plt.plot(filtered_data_z[X_COLUMN], filtered_data_z[Y_COLUMN])
            plt.title(f'ID: {data_id}, Z: {z_value}')
            plt.xlabel(X_COLUMN)
            plt.ylabel(Y_COLUMN)
            plt.show()
            # 关闭当前图表,释放内存
            plt.close(fig)
            
            user_input = input(f'Accept plot for ID {data_id} at Z {z_value}? (y/n/abort): ')
            if user_input.lower() == 'abort':
                pd.DataFrame(processed, columns=['ID', 'Z']).to_csv('processed_records.csv', index=False)
                return
            processed.append((data_id, z_value))

plot_data(data)

(2)优化Jupyter显示配置

在Notebook开头执行以下命令,降低内存占用并提升输出限制:

  • 改用轻量化图片格式:%config InlineBackend.figure_format='png'
  • 提升输出块数量上限:%config IPython.display.max_output_sections=1000

2. 大规模带用户输入绘图的最佳实践与替代方案

(1)用Jupyter交互式组件替代原生input()

原生input()在大量输入场景下易阻塞,体验差。改用ipywidgets构建交互式界面,更稳定且能自动记录反馈:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, clear_output

ID_COLUMN = 'ID'
Z_COLUMN = 'Z'
X_COLUMN = 'X'
Y_COLUMN = 'Y'

data = pd.DataFrame({
    ID_COLUMN: np.random.choice(['A', 'B', 'C'], 1000),
    Z_COLUMN: np.random.choice([10, 20, 30], 1000),
    X_COLUMN: np.random.rand(1000) * 100,
    Y_COLUMN: np.random.rand(1000) * 50
})

# 存储反馈结果
feedback_records = []

# 创建交互按钮
accept_btn = widgets.Button(description='Accept')
reject_btn = widgets.Button(description='Reject')
abort_btn = widgets.Button(description='Abort')
output = widgets.Output()

def on_accept(b):
    with output:
        clear_output(wait=True)
        feedback_records.append((current_id, current_z, 'accept'))
        next_plot()

def on_reject(b):
    with output:
        clear_output(wait=True)
        feedback_records.append((current_id, current_z, 'reject'))
        next_plot()

def on_abort(b):
    with output:
        clear_output(wait=True)
        pd.DataFrame(feedback_records, columns=['ID', 'Z', 'Feedback']).to_csv('feedback.csv', index=False)
        print('Aborted, feedback saved.')

accept_btn.on_click(on_accept)
reject_btn.on_click(on_reject)
abort_btn.on_click(on_abort)

# 生成所有待处理的(ID, Z)对
pending_items = []
for data_id in data[ID_COLUMN].unique():
    filtered_data = data[data[ID_COLUMN] == data_id]
    for z_value in filtered_data[Z_COLUMN].unique():
        pending_items.append((data_id, z_value))

current_index = 0
current_id, current_z = pending_items[current_index]

def next_plot():
    global current_index, current_id, current_z
    if current_index >= len(pending_items)-1:
        with output:
            clear_output(wait=True)
            pd.DataFrame(feedback_records, columns=['ID', 'Z', 'Feedback']).to_csv('feedback.csv', index=False)
            print('All plots processed!')
        return
    current_index += 1
    current_id, current_z = pending_items[current_index]
    plot_current()

def plot_current():
    with output:
        clear_output(wait=True)
        filtered_data_z = data[(data[ID_COLUMN]==current_id) & (data[Z_COLUMN]==current_z)]
        fig = plt.figure()
        plt.plot(filtered_data_z[X_COLUMN], filtered_data_z[Y_COLUMN])
        plt.title(f'ID: {current_id}, Z: {current_z}')
        plt.xlabel(X_COLUMN)
        plt.ylabel(Y_COLUMN)
        plt.show()
        plt.close(fig)

# 显示界面
display(widgets.HBox([accept_btn, reject_btn, abort_btn]))
display(output)
plot_current()

(2)预生成图表文件,批量审核

先将所有图表保存为本地文件,再用脚本批量浏览收集反馈,完全避开Jupyter的输出限制:

# 第一步:批量生成图表文件
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os

ID_COLUMN = 'ID'
Z_COLUMN = 'Z'
X_COLUMN = 'X'
Y_COLUMN = 'Y'

data = pd.DataFrame({
    ID_COLUMN: np.random.choice(['A', 'B', 'C'], 1000),
    Z_COLUMN: np.random.choice([10, 20, 30], 1000),
    X_COLUMN: np.random.rand(1000) * 100,
    Y_COLUMN: np.random.rand(1000) * 50
})

os.makedirs('plots', exist_ok=True)

for data_id in data[ID_COLUMN].unique():
    filtered_data = data[data[ID_COLUMN] == data_id]
    for z_value in filtered_data[Z_COLUMN].unique():
        filtered_data_z = filtered_data[filtered_data[Z_COLUMN] == z_value]
        fig = plt.figure()
        plt.plot(filtered_data_z[X_COLUMN], filtered_data_z[Y_COLUMN])
        plt.title(f'ID: {data_id}, Z: {z_value}')
        plt.xlabel(X_COLUMN)
        plt.ylabel(Y_COLUMN)
        plt.savefig(f'plots/ID_{data_id}_Z_{z_value}.png')
        plt.close(fig)

# 第二步:批量审核脚本
import glob
import cv2

feedback = []
plot_files = glob.glob('plots/*.png')

for file in plot_files:
    filename = os.path.basename(file)
    data_id = filename.split('_')[1]
    z_value = filename.split('_')[3].split('.')[0]
    
    img = cv2.imread(file)
    cv2.imshow(f'ID: {data_id}, Z: {z_value}', img)
    
    while True:
        key = cv2.waitKey(0)
        if key == ord('y'):
            feedback.append((data_id, z_value, 'accept'))
            break
        elif key == ord('n'):
            feedback.append((data_id, z_value, 'reject'))
            break
        elif key == ord('q'):
            pd.DataFrame(feedback, columns=['ID', 'Z', 'Feedback']).to_csv('feedback.csv', index=False)
            cv2.destroyAllWindows()
            exit()
    cv2.destroyAllWindows()

pd.DataFrame(feedback, columns=['ID', 'Z', 'Feedback']).to_csv('feedback.csv', index=False)

(3)改用独立GUI工具

如果Jupyter环境限制过多,可使用PyQt、Streamlit等工具构建独立审核界面,内存管理更灵活,适合大规模数据处理。比如Streamlit可快速搭建Web界面,支持图表显示和按钮输入,无需复杂GUI开发。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 07:50:04