1 代码的选择和改进

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from ipywidgets import (AppLayout, Dropdown, Button, Output, VBox, HBox, Label, Layout, SelectMultiple,IntSlider, FloatSlider, Checkbox, Text, Select)
from IPython.display import display, clear_output
import numpy as np
import os
from datetime import datetime
from traitlets import TraitError# 设置中文字体和样式
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "sans-serif"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = Falseclass EnhancedExcelVisualizer:def __init__(self, file_path1, file_path2):"""初始化增强版Excel数据可视化应用"""self.file_path1 = file_path1self.file_path2 = file_path2# 存储证券代码筛选状态self.selected_codes = []self.current_figure = None# 尝试加载文件try:self.excel_file1 = pd.ExcelFile(file_path1)self.excel_file2 = pd.ExcelFile(file_path2)self.sheet_names1 = self.excel_file1.sheet_namesself.sheet_names2 = self.excel_file2.sheet_namesexcept Exception as e:print(f"文件加载错误: {str(e)}")return# 当前状态变量self.current_data = Noneself.current_sheet = Noneself.current_file = Noneself.current_chart_type = 'line'self.figsize = (10, 6)self.color_palette = 'viridis'# 创建UI组件self.create_ui_components()# 显示UIself.display_ui()# 初始化self.update_sheet_selector()def create_ui_components(self):"""创建所有UI组件"""# 文件选择器file1_name = os.path.basename(self.file_path1)file2_name = os.path.basename(self.file_path2)self.file_selector = Dropdown(options=[f'文件1 ({file1_name})', f'文件2 ({file2_name})'],value=f'文件1 ({file1_name})',description='选择文件:',layout=Layout(width='100%'))# 工作表选择器self.sheet_selector = Dropdown(options=[],description='选择工作表:',layout=Layout(width='100%'))# 数据列选择器self.x_axis_selector = Dropdown(options=[],description='X轴数据列:',layout=Layout(width='100%'))self.y_axis_selector = SelectMultiple(options=[],description='Y轴数据列:',layout=Layout(width='100%'))# 证券代码筛选器self.code_selector = Text(value='589990.SH,589980.SH,589900.SH',description='证券代码 (逗号分隔):',layout=Layout(width='100%'))# 图表类型选择器self.chart_type_selector = Dropdown(options=['折线图', '柱状图', '面积图', '散点图', '箱线图', '热力图'],value='折线图',description='图表类型:',layout=Layout(width='100%'))# 图表样式控制self.color_palette_selector = Dropdown(options=['viridis', 'plasma', 'inferno', 'magma', 'cividis', 'Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2'],value='viridis',description='配色方案:',layout=Layout(width='100%'))self.figsize_slider = IntSlider(min=5, max=20, value=10, step=1,description='图表大小:',layout=Layout(width='100%'))self.rotation_slider = IntSlider(min=0, max=90, value=45, step=5,description='标签旋转:',layout=Layout(width='100%'))self.transparency_slider = FloatSlider(min=0.1, max=1.0, value=0.8, step=0.1,description='透明度:',layout=Layout(width='100%'))self.grid_checkbox = Checkbox(value=True,description='显示网格',layout=Layout(width='100%'))# 操作按钮self.refresh_button = Button(description='刷新图表',button_style='primary',icon='refresh',layout=Layout(width='100%'))self.export_button = Button(description='导出图表',button_style='info',icon='save',layout=Layout(width='100%'))# 输出区域self.data_preview_output = Output(layout=Layout(height='auto', max_height='300px', overflow='auto'))self.chart_output = Output(layout=Layout(height='500px', border='1px solid #e0e0e0'))self.stats_output = Output(layout=Layout(height='auto', max_height='300px', overflow='auto'))self.log_output = Output(layout=Layout(height='auto', max_height='200px', overflow='auto'))# 绑定事件self.file_selector.observe(self.on_file_change, names='value')self.sheet_selector.observe(self.on_sheet_change, names='value')self.chart_type_selector.observe(self.on_chart_type_change, names='value')self.refresh_button.on_click(self.refresh_chart)self.export_button.on_click(self.export_chart)self.code_selector.observe(self.on_code_change, names='value')# 样式控制绑定controls = [self.color_palette_selector, self.figsize_slider, self.rotation_slider, self.transparency_slider,self.grid_checkbox]for control in controls:control.observe(self.on_style_change, names='value')def on_file_change(self, change):"""处理文件选择变化事件"""with self.log_output:print(f"已选择文件: {change.new}")self.update_sheet_selector()def on_sheet_change(self, change):"""处理工作表选择变化事件"""with self.log_output:print(f"已选择工作表: {change.new}")self.update_column_selectors()def on_chart_type_change(self, change):"""处理图表类型变化事件"""with self.log_output:print(f"已选择图表类型: {change.new}")self.refresh_chart()def on_code_change(self, change):"""证券代码筛选变化事件处理"""codes = change.new.strip()if codes:self.selected_codes = [code.strip() for code in codes.split(',') if code.strip()]with self.log_output:print(f"已选择证券代码: {', '.join(self.selected_codes)}")else:self.selected_codes = []with self.log_output:print("未选择证券代码")self.refresh_chart()def on_style_change(self, change):"""处理样式变化事件"""with self.log_output:print(f"样式设置已更新: {change.owner.description} = {change.new}")self.refresh_chart()def update_sheet_selector(self):"""更新工作表选择器选项"""selected_file = self.file_selector.value.split(' ')[0]if selected_file == '文件1':self.sheet_selector.options = self.sheet_names1else:self.sheet_selector.options = self.sheet_names2if self.sheet_selector.options:self.sheet_selector.value = self.sheet_selector.options[0]def update_column_selectors(self):"""更新数据列选择器选项"""selected_file = self.file_selector.value.split(' ')[0]selected_sheet = self.sheet_selector.valueif not selected_sheet:self.x_axis_selector.options = []self.y_axis_selector.options = []returntry:if selected_file == '文件1':self.current_data = self.excel_file1.parse(selected_sheet)else:self.current_data = self.excel_file2.parse(selected_sheet)# 如果存在ts_code列且有筛选代码,则进行筛选if 'ts_code' in self.current_data.columns and self.selected_codes:self.current_data = self.current_data[self.current_data['ts_code'].isin(self.selected_codes)]except Exception as e:with self.log_output:print(f"读取工作表数据时出错: {str(e)}")returnself.current_sheet = selected_sheetself.current_file = selected_file# 更新列选择器column_names = list(self.current_data.columns)self.x_axis_selector.options = column_namesself.y_axis_selector.options = column_names# 自动选择默认列default_x = 'trade_date' if 'trade_date' in column_names else column_names[0]default_y = ['close'] if 'close' in column_names else (column_names[1:] if len(column_names) > 1 else [])self.x_axis_selector.value = default_xself.y_axis_selector.value = tuple(default_y) if default_y else ()# 更新数据预览和统计信息self.update_data_preview()self.update_stats()def update_data_preview(self):"""更新数据预览"""with self.data_preview_output:clear_output()if self.current_data is not None:display(self.current_data.head())def update_stats(self):"""更新统计信息"""with self.stats_output:clear_output()if self.current_data is not None:display(self.current_data.describe(include='all'))def refresh_chart(self, b=None):"""刷新图表显示"""x_axis = self.x_axis_selector.valuey_axes = self.y_axis_selector.valueif not x_axis or not y_axes or self.current_data is None:with self.chart_output:clear_output()print('请选择有效的X轴和Y轴数据列')returnwith self.chart_output:clear_output()plt.close('all')  # 清除之前的图形try:# 数据预处理if 'ts_code' in self.current_data.columns and self.selected_codes:filtered_data = self.current_data[self.current_data['ts_code'].isin(self.selected_codes)].dropna(subset=[x_axis] + list(y_axes)).copy()else:filtered_data = self.current_data.dropna(subset=[x_axis] + list(y_axes)).copy()if filtered_data.empty:print('所选列中没有有效数据或无匹配的证券代码')return# 设置图表大小self.figsize = (self.figsize_slider.value, self.figsize_slider.value*0.6)plt.figure(figsize=self.figsize)# 设置颜色sns.set_palette(self.color_palette_selector.value)# 图表类型处理chart_type = self.chart_type_selector.valueif chart_type == '折线图':self._draw_line_plot(filtered_data, x_axis, y_axes)elif chart_type == '柱状图':self._draw_bar_plot(filtered_data, x_axis, y_axes)elif chart_type == '面积图':self._draw_area_plot(filtered_data, x_axis, y_axes)elif chart_type == '散点图':self._draw_scatter_plot(filtered_data, x_axis, y_axes)elif chart_type == '箱线图':self._draw_box_plot(filtered_data, x_axis, y_axes)elif chart_type == '热力图':self._draw_heatmap(filtered_data, x_axis, y_axes)# 通用设置plt.grid(self.grid_checkbox.value)plt.tight_layout()self.current_figure = plt.gcf()plt.show()except Exception as e:with self.log_output:print(f"绘制图表时出错: {str(e)}")import tracebacktraceback.print_exc()def _draw_line_plot(self, data, x_axis, y_axes):"""绘制折线图"""# 尝试转换日期数据try:data[x_axis] = pd.to_datetime(data[x_axis])data = data.sort_values(by=x_axis)date_flag = Trueexcept:date_flag = Falseif 'ts_code' in data.columns and len(self.selected_codes) > 1:# 按证券代码分组绘制for code, group in data.groupby('ts_code'):for y_axis in y_axes:if pd.api.types.is_numeric_dtype(group[y_axis]):sns.lineplot(x=x_axis, y=y_axis, data=group,alpha=self.transparency_slider.value,label=f"{code}-{y_axis}")else:for y_axis in y_axes:if pd.api.types.is_numeric_dtype(data[y_axis]):sns.lineplot(x=x_axis, y=y_axis, data=data,alpha=self.transparency_slider.value,label=y_axis)plt.title(f'折线图: {", ".join(y_axes)} vs {x_axis}')plt.xlabel(x_axis)plt.ylabel('值')if date_flag:plt.xticks(rotation=self.rotation_slider.value)if len(y_axes) > 1 or ('ts_code' in data.columns and len(self.selected_codes) > 1):plt.legend(bbox_to_anchor=(1, 1), loc='upper left')def _draw_bar_plot(self, data, x_axis, y_axes):"""绘制柱状图"""if len(y_axes) != 1:with self.log_output:print('柱状图需要且仅需要一个Y轴')returny_axis = y_axes[0]if 'ts_code' in data.columns and len(self.selected_codes) > 1:# 按证券代码分组绘制for code, group in data.groupby('ts_code'):if pd.api.types.is_numeric_dtype(group[y_axis]):sns.barplot(x=x_axis, y=y_axis, data=group,alpha=self.transparency_slider.value,label=code)else:if pd.api.types.is_numeric_dtype(data[y_axis]):sns.barplot(x=x_axis, y=y_axis, data=data,alpha=self.transparency_slider.value)plt.title(f'柱状图: {y_axis} 按 {x_axis} 分布')plt.xlabel(x_axis)plt.ylabel(y_axis)plt.xticks(rotation=self.rotation_slider.value)if 'ts_code' in data.columns and len(self.selected_codes) > 1:plt.legend(bbox_to_anchor=(1, 1), loc='upper left')def _draw_area_plot(self, data, x_axis, y_axes):"""绘制面积图"""if len(y_axes) != 1:with self.log_output:print('面积图需要且仅需要一个Y轴')returny_axis = y_axes[0]if 'ts_code' in data.columns and len(self.selected_codes) > 1:# 按证券代码分组绘制for code, group in data.groupby('ts_code'):if pd.api.types.is_numeric_dtype(group[y_axis]):plt.fill_between(group[x_axis], group[y_axis],alpha=self.transparency_slider.value,label=code)else:if pd.api.types.is_numeric_dtype(data[y_axis]):plt.fill_between(data[x_axis], data[y_axis],alpha=self.transparency_slider.value)plt.title(f'面积图: {y_axis} 按 {x_axis} 分布')plt.xlabel(x_axis)plt.ylabel(y_axis)plt.xticks(rotation=self.rotation_slider.value)if 'ts_code' in data.columns and len(self.selected_codes) > 1:plt.legend(bbox_to_anchor=(1, 1), loc='upper left')def _draw_scatter_plot(self, data, x_axis, y_axes):"""绘制散点图"""if len(y_axes) != 1:with self.log_output:print('散点图需要且仅需要一个Y轴')returny_axis = y_axes[0]if 'ts_code' in data.columns and len(self.selected_codes) > 1:# 按证券代码分组绘制for code, group in data.groupby('ts_code'):if pd.api.types.is_numeric_dtype(group[x_axis]) and pd.api.types.is_numeric_dtype(group[y_axis]):sns.scatterplot(x=x_axis, y=y_axis, data=group,alpha=self.transparency_slider.value,label=code)else:if pd.api.types.is_numeric_dtype(data[x_axis]) and pd.api.types.is_numeric_dtype(data[y_axis]):sns.scatterplot(x=x_axis, y=y_axis, data=data,alpha=self.transparency_slider.value)plt.title(f'散点图: {y_axis} vs {x_axis}')plt.xlabel(x_axis)plt.ylabel(y_axis)if 'ts_code' in data.columns and len(self.selected_codes) > 1:plt.legend(bbox_to_anchor=(1, 1), loc='upper left')def _draw_box_plot(self, data, x_axis, y_axes):"""绘制箱线图"""if len(y_axes) != 1:with self.log_output:print('箱线图需要且仅需要一个Y轴')returny_axis = y_axes[0]if 'ts_code' in data.columns and len(self.selected_codes) > 1:# 按证券代码分组绘制for code, group in data.groupby('ts_code'):if pd.api.types.is_numeric_dtype(group[y_axis]):sns.boxplot(x=group[x_axis], y=y_axis, data=group,alpha=self.transparency_slider.value,label=code)else:if pd.api.types.is_numeric_dtype(data[y_axis]):sns.boxplot(x=x_axis, y=y_axis, data=data)plt.title(f'箱线图: {y_axis} 按 {x_axis} 分布')plt.xlabel(x_axis)plt.ylabel(y_axis)plt.xticks(rotation=self.rotation_slider.value)if 'ts_code' in data.columns and len(self.selected_codes) > 1:plt.legend(bbox_to_anchor=(1, 1), loc='upper left')def _draw_heatmap(self, data, x_axis, y_axes):"""绘制热力图"""if len(y_axes) < 2:with self.log_output:print('热力图需要至少两个Y轴')return# 选择数值列numeric_cols = [col for col in y_axes if pd.api.types.is_numeric_dtype(data[col])]if len(numeric_cols) < 2:with self.log_output:print('热力图需要至少两个数值列')return# 计算相关系数corr = data[numeric_cols].corr()# 绘制热力图sns.heatmap(corr, annot=True, cmap=self.color_palette_selector.value,fmt=".2f", linewidths=.5)plt.title('热力图: 相关系数矩阵')plt.xticks(rotation=self.rotation_slider.value)plt.yticks(rotation=0)def export_chart(self, b):"""导出图表"""if not hasattr(self, 'current_figure'):with self.log_output:print('没有可导出的图表')return# 包含证券代码信息在文件名中code_str = '_'.join(self.selected_codes) if self.selected_codes else 'all_codes'chart_type = self.chart_type_selector.valuetimestamp = datetime.now().strftime("%Y%m%d_%H%M%S")filename = f"chart_{chart_type}_{code_str}_{timestamp}.png"try:self.current_figure.savefig(filename, dpi=300, bbox_inches='tight')with self.log_output:print(f'图表已成功导出为: {filename}')except Exception as e:with self.log_output:print(f'导出图表时出错: {str(e)}')def display_ui(self):"""显示应用界面"""# 控制面板control_panel = VBox([self.file_selector,self.sheet_selector,self.x_axis_selector,self.y_axis_selector,self.code_selector,self.chart_type_selector,self.color_palette_selector,self.figsize_slider,self.rotation_slider,self.transparency_slider,self.grid_checkbox,HBox([self.refresh_button, self.export_button])], layout=Layout(width='30%', padding='10px'))# 输出面板output_panel = VBox([Label('📊 数据预览'),self.data_preview_output,Label('📈 数据统计'),self.stats_output,Label('✨ 数据可视化'),self.chart_output,Label('📝 日志信息'),self.log_output], layout=Layout(width='70%', padding='10px'))# 整体布局app_layout = HBox([control_panel, output_panel])# 显示应用display(app_layout)# 使用示例
if __name__ == "__main__":# 修改为您的Excel文件路径file_path1 = 'G:\\PyCharm\\Python_project\\daily_chart.xlsx'file_path2 = 'G:\\PyCharm\\Python_project\\daily_market_data.xlsx'# 创建并显示应用app = EnhancedExcelVisualizer(file_path1, file_path2)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime# 设置中文显示和美观的图表样式
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
sns.set_style("whitegrid", {'font.sans-serif':['simhei','Arial']})# 1. 数据加载 - 修改后支持多个文件
def load_data():# 指定文件路径列表file_paths = [r'G:\PyCharm\Python_project\output.xlsx',r'G:\PyCharm\Python_project\output1.xlsx',r'G:\PyCharm\Python_project\output3.xlsx']all_data = []# 循环读取每个文件for file_path in file_paths:try:# 读取Excel文件df = pd.read_excel(file_path, sheet_name='Sheet1')# 转换日期格式(假设原始日期是整数格式如20250627)df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')# 添加市场类型列(SH表示上海,SZ表示深圳)df['market'] = df['ts_code'].str[-3:]# 添加文件名信息,便于追踪数据来源df['source_file'] = file_path.split('\\')[-1]all_data.append(df)print(f"成功加载文件: {file_path}")except Exception as e:print(f"加载文件 {file_path} 时出错: {e}")# 合并所有数据if all_data:combined_df = pd.concat(all_data, ignore_index=True)print(f"已合并所有数据,总记录数: {len(combined_df)}")return combined_dfelse:print("没有成功加载任何数据!")return pd.DataFrame()# 2. 数据探索分析
def explore_data(df):if df.empty:print("没有数据可分析!")returnprint("="*50)print("基本数据信息:")print(f"总记录数: {len(df)}")print(f"日期范围: {df['trade_date'].min()} 到 {df['trade_date'].max()}")print(f"唯一证券数量: {df['ts_code'].nunique()}")print(f"市场分布:\n{df['market'].value_counts()}")print("\n调整因子描述统计:")print(df['adj_factor'].describe())# 非1的调整因子统计non_one = df[df['adj_factor'] != 1]print(f"\n需要调整的证券数量: {len(non_one)} ({len(non_one)/len(df):.2%})")print("这些证券的描述统计:")print(non_one['adj_factor'].describe())# 按市场分类统计print("\n按市场分类的调整因子统计:")print(df.groupby('market')['adj_factor'].describe())# 按文件来源分类统计print("\n按文件来源分类的调整因子统计:")print(df.groupby('source_file')['adj_factor'].describe())# 找出调整因子最大和最小的10个证券top10 = df.nlargest(10, 'adj_factor')[['ts_code', 'trade_date', 'adj_factor', 'source_file']]bottom10 = df.nsmallest(10, 'adj_factor')[['ts_code', 'trade_date', 'adj_factor', 'source_file']]print("\n调整因子最大的10个证券:")print(top10)print("\n调整因子最小的10个证券:")print(bottom10)# 3. 数据可视化
def visualize_data(df):if df.empty:print("没有数据可可视化!")return# 设置图表大小plt.figure(figsize=(15, 10))# 调整因子分布直方图plt.subplot(2, 2, 1)bins = np.logspace(np.log10(df['adj_factor'].min()), np.log10(df['adj_factor'].max()), 50)plt.hist(df['adj_factor'], bins=bins)plt.xscale('log')plt.title('调整因子分布(对数刻度)')plt.xlabel('调整因子(log scale)')plt.ylabel('数量')# 按市场分类的箱线图plt.subplot(2, 2, 2)sns.boxplot(x='market', y='adj_factor', data=df)plt.title('不同市场的调整因子分布')plt.yscale('log')  # 使用对数刻度以便更好地观察# 时间变化分析(比较两天的调整因子)if df['trade_date'].nunique() > 1:plt.subplot(2, 2, 3)changed = get_changed_securities(df)if not changed.empty:sns.scatterplot(x='adj_factor_prev', y='adj_factor', data=changed)plt.plot([0.1, 30], [0.1, 30], 'r--')  # 添加对角线plt.xscale('log')plt.yscale('log')plt.title('调整因子变化情况(前后两天比较)')plt.xlabel('前一天调整因子')plt.ylabel('当天调整因子')# 调整因子不为1的证券数量按市场分布plt.subplot(2, 2, 4)non_one = df[df['adj_factor'] != 1]if not non_one.empty:sns.countplot(x='market', data=non_one)plt.title('需要调整的证券数量按市场分布')plt.tight_layout()plt.show()# 新增图表:按文件来源显示调整因子分布plt.figure(figsize=(12, 6))sns.boxplot(x='source_file', y='adj_factor', data=df)plt.title('不同文件来源的调整因子分布')plt.yscale('log')plt.xticks(rotation=45)plt.tight_layout()plt.show()# 4. 找出调整因子发生变化的证券
def get_changed_securities(df):if df['trade_date'].nunique() < 2:print("数据中日期数量不足,无法比较调整因子变化!")return pd.DataFrame()# 获取日期排序dates = sorted(df['trade_date'].unique())# 确保有足够的日期进行比较if len(dates) < 2:print("数据中日期数量不足,无法比较调整因子变化!")return pd.DataFrame()# 合并前后两天的数据prev_day = df[df['trade_date'] == dates[-2]].copy()curr_day = df[df['trade_date'] == dates[-1]].copy()merged = pd.merge(prev_day, curr_day, on='ts_code', suffixes=('_prev', ''), how='outer')# 只保留有变化的证券changed = merged[merged['adj_factor_prev'] != merged['adj_factor']]return changed# 5. 主函数
def main():# 加载数据df = load_data()# 数据探索explore_data(df)# 数据可视化visualize_data(df)# 找出变化的证券changed = get_changed_securities(df)if not changed.empty:print("\n调整因子发生变化的证券:")print(changed[['ts_code', 'adj_factor_prev', 'adj_factor', 'source_file']])print(f"\n调整因子变化的证券数量: {len(changed)}")else:print("\n没有证券的调整因子发生变化")if __name__ == "__main__":main()

 

以下是对两份代码的详细对比分析,从功能、架构、用户体验等多个维度梳理改进点与差异,并解释为何最终选择代码 2:

一、功能对比与改进

1. 数据处理能力
  • 代码 1

    • 支持加载 2 个 Excel 文件,通过文件选择器切换。
    • 可筛选特定证券代码(通过ts_code列),但需手动输入逗号分隔的代码。
    • 数据预处理仅包含简单的空值过滤,未对日期格式、市场类型等进行标准化处理。
  • 代码 2

    • 改进 1:支持加载多个文件(通过列表指定路径),自动合并数据,提升数据处理效率。
    • 改进 2:新增日期格式转换(将整数日期转为datetime类型),便于时间序列分析。
    • 改进 3:添加market列(通过ts_code后缀识别上海 / 深圳市场),支持按市场分类统计。
    • 改进 4:添加source_file列追踪数据来源,便于后续溯源和分析。
2. 数据分析深度
  • 代码 1

    • 核心功能为数据可视化,支持多种图表类型(折线图、柱状图等),但数据分析逻辑较少。
    • 仅提供数据预览和基础统计描述(describe()),未针对业务场景(如调整因子)做专项分析。
  • 代码 2

    • 改进 5:新增explore_data函数,深度分析调整因子:
      • 统计需要调整的证券比例(adj_factor != 1)。
      • 按市场、文件来源分组统计调整因子分布。
      • 筛选调整因子最大 / 最小的证券,定位异常值。
    • 改进 6:新增get_changed_securities函数,对比前后两天调整因子变化,识别波动证券。

二、可视化与交互设计差异

1. 可视化功能
  • 代码 1

    • 优势:提供交互式图表界面,支持动态切换图表类型、配色、尺寸等参数。
    • 不足:图表逻辑分散在多个私有方法(如_draw_line_plot),维护性较差;部分图表(如热力图)需手动指定多列,使用门槛较高。
  • 代码 2

    • 改进 7:可视化逻辑更聚焦业务场景,例如:
      • 调整因子分布直方图(对数刻度,适配宽范围数据)。
      • 按市场分类的箱线图(对数刻度,突出异常值)。
      • 调整因子变化散点图(对角线辅助线,直观展示波动)。
    • 改进 8:图表布局更紧凑(subplot分块),一次性展示多维度分析结果,便于综合判断。
2. 交互方式
  • 代码 1

    • 采用 IPython 交互式组件(Dropdown、Slider 等),需在 Jupyter 环境中运行,适合实时探索。
    • 操作流程较复杂(需依次选择文件、工作表、坐标轴),新手使用可能存在学习成本。
  • 代码 2

    • 改进 9:采用脚本化执行方式,无需手动交互,一键运行即可输出完整分析报告,适合批量处理。
    • 改进 10:输出内容包含文本统计结果和图表,信息呈现更系统化,便于汇报和存档。

三、架构与可维护性

1. 代码结构
  • 代码 1

    • 采用类封装(EnhancedExcelVisualizer),但方法耦合度较高(如 UI 组件创建与图表绘制混合)。
    • 异常处理较简单,仅在文件加载时捕获错误,其他环节(如数据处理、图表绘制)的异常可能导致程序崩溃。
  • 代码 2

    • 改进 11:采用函数式编程,模块职责清晰(load_dataexplore_data等),便于后续扩展。
    • 改进 12:异常处理更全面,每个文件加载环节均有独立的错误捕获,避免单个文件失败导致整个程序中断。
2. 可扩展性
  • 代码 1

    • 扩展新图表类型需修改refresh_chart和对应绘图方法,成本较高。
    • 数据处理逻辑固定,难以适配不同格式的输入数据。
  • 代码 2

    • 改进 13:数据加载模块可灵活扩展文件路径列表,支持添加更多数据源。
    • 改进 14:分析函数(如explore_data)可通过新增分组条件或统计指标快速扩展,适配不同业务需求。

四、为何最终选择代码 2?

1. 业务适配性更强
  • 代码 2 专门针对 “调整因子分析” 场景设计,包含从数据加载、探索到可视化的完整流程,直接解决业务问题。
  • 代码 1 更偏向通用数据可视化工具,缺乏对特定业务指标(如调整因子变化)的深度分析。
2. 执行效率与稳定性更高
  • 代码 2 采用脚本化执行,无需手动交互,适合批量处理多文件数据,执行效率更高。
  • 模块化设计和全面的异常处理确保程序稳定性,适合生产环境使用。
3. 结果呈现更清晰
  • 代码 2 的输出包含文本统计和多维度图表,信息组织更系统,便于业务人员理解和决策。
  • 代码 1 的交互式界面虽灵活,但需要用户手动操作才能获取结果,不适合生成标准化报告。
4. 维护与扩展成本更低
  • 代码 2 的函数式架构更简洁,新增功能(如分析其他指标、接入新数据源)时只需修改对应函数,维护成本低。
  • 代码 1 的类封装虽复杂,但 UI 组件与业务逻辑耦合,扩展时可能影响整体功能。

总结:改进与差异汇总表

对比维度代码 1代码 2(改进点)
数据处理2 文件加载,简单过滤多文件合并,日期 / 市场标准化处理
业务分析通用可视化,缺乏深度业务逻辑聚焦调整因子分析,支持变化追踪
可视化交互式图表,类型多样业务场景化图表,对数刻度优化
交互方式Jupyter 交互式组件,手动操作脚本化执行,一键生成报告
架构设计类封装,耦合度较高函数式编程,模块职责清晰
适用场景数据探索与可视化实验业务指标分析、批量报告生成

代码 2 通过更聚焦的业务逻辑、更稳健的架构和更高效的执行方式,更适合实际业务场景中的数据分析需求,因此最终选择代码 2。

2 模拟答辩

项目答辩过程日志

一、答辩基本信息

  • 答辩时间:2025 年 6 月 30 日 14:00-14:30
  • 答辩地点:线上会议室
  • 答辩项目:基于 Python 的证券调整因子分析系统
  • 参与评委:张教授、李老师、王工程师

二、答辩流程记录

1. 开场陈述(5 分钟)

  • 自我介绍:简要介绍自己的学习背景和项目参与经历
  • 项目背景
    • 证券市场中调整因子是复权计算的关键指标,直接影响价格走势分析的准确性
    • 现有工具缺乏对调整因子系统性分析,难以快速定位异常证券
  • 项目目标
    • 开发一个能批量处理多源数据的调整因子分析系统
    • 实现从数据加载、探索分析到可视化的全流程自动化
    • 支持调整因子变化追踪和异常值识别
  • 选择代码 2 的原因
    • 相比代码 1 更聚焦业务场景,能直接解决调整因子分析需求
    • 模块化设计更适合生产环境,可扩展性和维护性更强
    • 脚本化执行方式适合批量处理,能快速生成标准化分析报告

2. 项目功能演示(10 分钟)

(1)数据加载功能演示
  • 展示代码中文件路径配置:

python

运行

file_paths = [r'G:\PyCharm\Python_project\output.xlsx',r'G:\PyCharm\Python_project\output1.xlsx',r'G:\PyCharm\Python_project\output3.xlsx'
]
  • 演示数据加载过程,包括:
    • 自动读取多个 Excel 文件并合并数据
    • 日期格式自动转换(如 20250627 转为 datetime 类型)
    • 自动添加 market 列(根据 ts_code 后缀识别市场)
    • 自动添加 source_file 列追踪数据来源
  • 展示加载成功后的日志输出:

plaintext

成功加载文件: G:\PyCharm\Python_project\output.xlsx
成功加载文件: G:\PyCharm\Python_project\output1.xlsx
成功加载文件: G:\PyCharm\Python_project\output3.xlsx
已合并所有数据,总记录数: 12543
(2)数据探索分析功能演示
  • 运行 explore_data 函数,展示文本分析结果:
    • 基本数据信息(记录数、日期范围、证券数量等)
    • 调整因子描述统计
    • 需要调整的证券数量及占比
    • 按市场和文件来源分组的调整因子统计
    • 调整因子最大和最小的 10 个证券列表
  • 关键输出示例:

plaintext

需要调整的证券数量: 3256 (25.97%)
调整因子最大的10个证券:ts_code trade_date  adj_factor        source_file
0  688001.SH 2025-06-27     5.234  output3.xlsx
1  688002.SH 2025-06-27     4.876  output1.xlsx
...
调整因子最小的10个证券:ts_code trade_date  adj_factor        source_file
0  000001.SZ 2025-06-27     0.125  output.xlsx
1  000002.SZ 2025-06-27     0.156  output.xlsx
...
(3)数据可视化功能演示
  • 展示自动生成的多维度分析图表:
    • 调整因子分布直方图(对数刻度)
    • 按市场分类的调整因子箱线图
    • 调整因子变化散点图(含对角线辅助线)
    • 按市场分布的需要调整证券数量柱状图
    • 按文件来源分类的调整因子箱线图
  • 特别说明图表设计亮点:
    • 使用对数刻度处理宽范围数据,使分布特征更明显
    • 散点图中添加对角线辅助线,直观展示调整因子变化
    • 子图布局合理,便于综合分析
(4)调整因子变化追踪功能演示
  • 运行 get_changed_securities 函数,展示:
    • 前后两天调整因子发生变化的证券列表
    • 变化证券数量统计
  • 示例输出:

plaintext

调整因子发生变化的证券:ts_code  adj_factor_prev  adj_factor        source_file
0  600001.SH              1.256          1.324  output.xlsx
1  600002.SH              2.345          2.112  output.xlsx
...
调整因子变化的证券数量: 876

3. 评委提问与回答(12 分钟)

(1)张教授提问:
  • 问题:为什么选择函数式编程而不是类封装方式?
  • 回答
    • 函数式编程使模块职责更清晰,每个函数专注于特定功能
    • 便于后续扩展,新增功能只需添加新函数或修改对应函数
    • 脚本化执行方式更适合批量处理和生成标准化报告
    • 在这个特定业务场景下,函数式编程比类封装更简洁高效
(2)李老师提问:
  • 问题:代码中使用对数刻度的图表设计是出于什么考虑?
  • 回答
    • 调整因子的取值范围通常较大,从 0.1 到 5 以上不等
    • 线性刻度下,小值区间的分布特征会被压缩难以观察
    • 使用对数刻度可以均匀展示整个取值范围的分布情况
    • 特别是在箱线图中,对数刻度能更好地展示异常值
(3)王工程师提问:
  • 问题:如果需要分析其他指标,这个系统容易扩展吗?
  • 回答
    • 系统采用模块化设计,各功能解耦良好
    • 扩展其他指标分析主要涉及:
      • 在 load_data 函数中添加对新指标的处理
      • 新增 explore_xxx 函数进行专项分析
      • 新增 visualize_xxx 函数进行可视化展示
    • 以调整因子分析模块为参考,扩展其他指标难度较低
    • 示例:若要分析收盘价,可以添加专门的收盘价分析函数
(4)张教授追问:
  • 问题:相比代码 1,代码 2 在处理大数据量时表现如何?
  • 回答
    • 代码 1 采用交互式设计,在大数据量下可能会有性能问题
    • 代码 2 采用脚本化执行,一次性处理所有数据
    • 关键优化点:
      • 使用 pandas 的 concat 进行高效数据合并
      • 避免不必要的交互式组件渲染
      • 图表生成时进行必要的数据过滤
    • 在测试中,处理 10 万条记录时代码 2 仍能保持良好性能
(5)李老师追问:
  • 问题:系统在实际应用中可能存在哪些局限性?
  • 回答
    • 目前假设所有文件都包含相同的列结构,若结构不同需要手动调整
    • 调整因子变化分析仅比较前后两天数据,更长时间跨度的分析需要扩展
    • 图表类型相对固定,复杂的可视化需求可能需要进一步开发
    • 缺乏用户界面,不适合非技术人员直接使用

4. 总结陈述(3 分钟)

  • 项目成果
    • 成功开发了一个功能完整的证券调整因子分析系统
    • 实现了多源数据加载、深度分析和可视化展示
    • 能够快速定位调整因子异常证券和变化情况
  • 技术亮点
    • 多文件批量处理和自动合并
    • 业务场景化的深度分析和可视化
    • 对数刻度等数据可视化优化
    • 模块化设计保证可扩展性
  • 未来改进方向
    • 添加用户界面,方便非技术人员使用
    • 扩展更多分析维度和指标
    • 增加数据导出功能,方便报告生成
    • 优化大数据处理性能

三、答辩评价与反馈

1. 评委综合评价

  • 张教授:项目选题具有实际应用价值,代码结构清晰,能够很好地解决证券调整因子分析问题,对数刻度的图表设计很有亮点。
  • 李老师:数据处理流程完整,从加载到分析再到可视化形成了闭环,特别是调整因子变化追踪功能很有实用价值。
  • 王工程师:系统设计考虑了实际应用场景,模块化设计使得系统具有较好的可扩展性,适合在实际业务中应用。

2. 改进建议

  • 添加数据校验功能,确保不同结构的文件能够正确处理
  • 增加分析结果导出功能,方便生成正式报告
  • 考虑添加简单的用户界面,提升系统易用性
  • 完善异常处理机制,提高系统稳定性

3. 答辩结果

  • 答辩通过,评价等级:良好
  • 建议根据评委意见进行改进后,可考虑在实际业务中试用

四、答辩总结与反思

1. 成功经验

  • 充分理解业务需求,确保项目具有实际应用价值
  • 采用模块化设计,提高系统可扩展性和可维护性
  • 注重数据可视化效果,使用合适的图表和刻度展示数据特征
  • 提前准备充分,对项目的各个环节都有深入的理解

2. 不足之处

  • 对系统在大数据量下的性能测试不够充分
  • 用户界面设计方面考虑不足
  • 异常处理机制还可以进一步完善
  • 文档说明不够详细,特别是函数参数和返回值的说明

3. 后续改进计划

  • 针对评委建议,逐步完善系统功能
  • 进行大数据量测试,优化系统性能
  • 设计简单的用户界面,提升系统易用性
  • 完善文档说明,方便后续维护和扩展
  • 寻找实际应用场景,在实践中检验和改进系统

通过本次答辩,不仅展示了项目成果,也获得了宝贵的反馈意见。接下来将根据评委建议,进一步完善系统,使其更具实用性和推广价值。

3 踩坑实录

1 matplotlib 库环境 换源
修改了生成 .condarc 文件,做了很多镜像通道的尝试...还是pip指令比较好
2 # 必须在 Jupyter Notebook 的第一行添加以下魔术指令
%matplotlib inline
3 数据跑不起来图的原因测试中...:读取?最小化测试通过,读取的逻辑没有问题绘制显示? matplotlib验证过了可以用,可以显示
4 事件绑定刷新不同按钮的时候 refresh逻辑优化这样才能生成不同的图表(可是有些数据本来就不能够绘图)
5 新的tkinter库窗口结合数据,显示读取数据成功,但是依旧画出空的图像,有底图,路径也可以成功保存但是模拟数据(内置的写死的)可以绘图
.....哎
问题就是交互式页面数据的结合,有点头疼,怎么修复都没发现,应该是数据代码隐含的逻辑存在问题吧?

结合你之前在数据可视化和交互开发中遇到的问题,以下是针对文档中提到的坑的详细分析与解决方案,覆盖环境配置、数据读取、图表绘制及交互逻辑等关键环节:

一、环境配置与镜像问题

踩坑回顾
  • 修改.condarc文件配置镜像通道失败,最终通过pip指令换源解决。
解决方案
  1. 推荐 pip 换源方案(永久配置)
    在命令行执行:

    bash

    # 阿里云镜像
    pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
    # 验证配置
    pip config list
    
  2. Jupyter 环境验证
    在 Notebook 中运行:

    python

    运行

    import matplotlib
    print(f"matplotlib版本: {matplotlib.__version__}")
    print(f"配置路径: {matplotlib.get_configdir()}")
    

    确保无ModuleNotFoundError或版本冲突。

二、% matplotlib inline 魔术指令

踩坑回顾
  • 需在 Notebook 第一行添加该指令,否则图表可能无法显示。
扩展说明
  1. 指令原理
    • %matplotlib inline:将图表嵌入 Notebook 单元格内,适合交互式探索。
    • 替代方案(如%matplotlib tk):弹出独立窗口,但不利于报告生成。
  2. 最佳实践
    在 Notebook 开头统一添加:

    python

    运行

    %matplotlib inline
    import matplotlib.pyplot as plt
    plt.rcParams["font.family"] = ["SimHei", "sans-serif"]  # 解决中文显示
    

三、数据读取与图表空白问题

踩坑回顾
  • 单独测试数据读取和 matplotlib 绘图正常,但结合交互逻辑后图表为空。
深度排查步骤
  1. 数据有效性验证
    在绘图前添加:

    python

    运行

    def plot_data(data):# 数据预处理检查print(f"数据行数: {len(data)}")print(f"空值数量: {data.isna().sum().sum()}")print(f"数值列统计: {data.select_dtypes(include='number').describe()}")# 示例:绘制前5行数据if not data.empty:plt.plot(data.head()['x_col'], data.head()['y_col'])else:plt.text(0.5, 0.5, "数据为空", ha='center', va='center', transform=plt.gca().transAxes)
    
  2. 交互场景下的数据传递
    • 若使用tkinter,需确认:
      • 数据是否通过StringVar/DataFrame正确绑定到界面组件。
      • 事件触发时(如按钮点击)是否重新加载数据。
    • 示例:Button(command=lambda: plot_data(df)) 需确保df为最新数据。

四、事件绑定与 refresh 逻辑优化

踩坑回顾
  • 刷新按钮未正确触发图表更新,或因数据格式问题导致绘图失败。
优化方案
  1. 分层事件处理架构

    python

    运行

    def on_refresh():try:# 1. 数据获取data = load_data_from_ui()# 2. 数据校验if data.empty:show_error("数据为空,请检查输入")return# 3. 图表绘制update_chart(data)except Exception as e:show_error(f"绘图错误: {str(e)}")def update_chart(data):plt.clf()  # 清除旧图表# 根据数据类型选择绘图方式if is_time_series(data):plot_time_series(data)else:plot_scatter(data)plt.draw()
    
  2. 错误状态可视化
    当数据无法绘图时,显示提示信息:

    python

    运行

    def plot_error():plt.clf()plt.text(0.5, 0.5, "无法绘制图表\n请检查数据格式", ha='center', va='center', fontsize=12)plt.axis('off')plt.draw()
    

五、tkinter 与数据可视化结合问题

踩坑回顾
  • tkinter 窗口显示数据读取成功,但图表为空;内置模拟数据可正常绘图。
解决方案
  1. matplotlib 与 tkinter 集成方案
    使用FigureCanvasTkAgg嵌入图表:

    python

    运行

    import tkinter as tk
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAggdef create_tk_chart(root, data):fig, ax = plt.subplots(figsize=(8, 6))if not data.empty:ax.plot(data['x'], data['y'])else:ax.text(0.5, 0.5, "无数据", ha='center', va='center')ax.set_title("数据图表")canvas = FigureCanvasTkAgg(fig, master=root)canvas.draw()canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)return canvas
    
  2. 数据路径与权限检查
    • 使用绝对路径读取文件:os.path.abspath("data.xlsx")
    • 验证文件权限:os.access(file_path, os.R_OK)
    • 示例错误处理:

      python

      运行

      if not os.path.exists(file_path):raise FileNotFoundError(f"文件不存在: {file_path}")
      

六、综合调试流程建议

  1. 最小可行示例(MVE)验证
    • 先实现不依赖 UI 的纯数据绘图函数,确保核心逻辑正确。
    • 再逐步集成 UI 组件,每次添加一个功能(如按钮、数据输入框)。
  2. 日志与调试工具
    • 在关键节点添加print日志:print(f"当前数据形状: {data.shape}")
    • 使用pdb调试器:import pdb; pdb.set_trace()
  3. 版本控制与回滚
    • 每次修改前通过git commit保存进度,便于回滚到稳定版本。

七、历史问题复盘与预防

问题类型之前踩的坑预防措施
环境配置.condarc镜像失效统一使用pip config配置镜像
图表显示未添加 % matplotlib inline在 Notebook 开头固定添加魔术指令
数据空值读取数据后未校验空值绘图前强制检查data.empty
交互逻辑按钮事件未正确触发数据更新采用分层事件处理架构,分离数据与视图
tkinter 集成图表空白但数据存在使用FigureCanvasTkAgg正确嵌入图表

通过以上方案,可系统性解决环境、数据、交互等层面的问题,确保可视化功能稳定运行。建议按 “数据校验→核心绘图→UI 集成” 的顺序逐步调试,每次聚焦一个模块的问题。

4 成长小结

项目答辩:踩坑成长与代码改进之路

一、开场:从问题出发的成长叙事

各位评委老师好!今天我想通过 "踩坑 - 反思 - 改进" 的真实历程,分享我在开发证券数据可视化系统中的技术成长。项目最初只是一个简单的图表绘制脚本,却在实际应用中不断遇到挑战 —— 从环境配置失败到交互逻辑混乱,从数据可视化空白到多源数据处理难题。每一个坑都倒逼我重新思考代码设计,最终形成了现在这套更健壮的分析系统。下面我将以 "问题导向" 的方式,呈现这段改进之路。

二、第一阶段:环境与基础功能的坑(代码 1 雏形)

1. 坑 1: matplotlib 换源配置反复失败

  • 踩坑经历
    最初按教程修改.condarc文件配置镜像,以为配置成功但安装库时仍报错。花了 3 小时排查才发现:
    • Anaconda 镜像优先级高于 pip,导致.condarc配置失效
    • 不同环境(Jupyter / 终端)的镜像配置可能冲突
  • 改进代码
    放弃.condarc,改用 pip 永久换源:

    bash

    pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
    
  • 成长收获
    认识到环境配置需遵循 "最小依赖" 原则,pip 换源比 conda 更直接可靠。

2. 坑 2:Jupyter 图表不显示之谜

  • 踩坑经历
    写好的绘图代码在 Jupyter 中运行只输出空白,检查发现:
    • 未添加%matplotlib inline魔术指令
    • 中文字体未配置导致图表渲染失败
  • 改进代码
    在 Notebook 开头固定添加:

    python

    运行

    %matplotlib inline
    plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei"]
    plt.rcParams["axes.unicode_minus"] = False
    
  • 成长收获
    总结出 Jupyter 绘图 "三板斧":魔术指令 + 字体配置 + 错误捕获。

三、第二阶段:数据处理与可视化的坑(代码 1 优化)

1. 坑 3:交互式图表数据空白

  • 踩坑经历
    点击刷新按钮后图表空白,但单独测试数据读取和绘图正常,定位到:
    • 交互事件触发时未正确传递最新数据
    • 数据中存在空值未处理
    • 绘图前未校验数据有效性
  • 改进代码
    添加数据校验函数:

    python

    运行

    def validate_data(data):if data.empty:raise ValueError("数据为空,无法绘图")na_count = data.isna().sum().sum()if na_count > 0:print(f"警告:数据包含{na_count}个空值,已过滤")return data.dropna()return data
    

    在绘图前强制调用:

    python

    运行

    try:valid_data = validate_data(user_data)plot_chart(valid_data)
    except ValueError as e:show_warning(e)
    
  • 成长收获
    建立 "数据校验 - 异常处理 - 错误可视化" 的完整流程,避免 "黑盒" 错误。

2. 坑 4:图表类型与数据不匹配

  • 踩坑经历
    用折线图绘制分类数据时图表混乱,发现:
    • 未根据数据类型自动选择图表类型
    • 柱状图 / 折线图的参数配置混用
  • 改进代码
    添加智能图表类型判断:

    python

    运行

    def auto_select_chart(data, x_col, y_col):if is_numeric(data[y_col]) and is_time_series(data[x_col]):return "line"  # 时间序列折线图elif is_categorical(data[x_col]):return "bar"   # 分类数据柱状图else:return "scatter"
    
  • 成长收获
    认识到数据可视化需 "量体裁衣",建立数据类型与图表类型的映射规则。

四、第三阶段:架构与工程化的坑(转向代码 2)

1. 坑 5:交互式界面与业务逻辑耦合

  • 踩坑经历
    代码 1 的EnhancedExcelVisualizer类中,UI 组件创建与数据处理逻辑混杂:
    • 修改一个按钮事件需牵动整个类
    • 新增图表类型时需重写refresh_chart方法
    • 难以复用数据处理逻辑到其他场景
  • 改进方案
    转向代码 2 的函数式架构,将系统拆分为:

    python

    运行

    # 模块化拆分示例
    data = load_data()          # 数据加载
    explored = explore_data(data)  # 分析逻辑
    visualize_data(explored)      # 可视化
    
  • 成长收获
    理解 "关注点分离" 原则,函数式架构更适合业务逻辑的扩展与复用。

2. 坑 6:多源数据处理效率低下

  • 踩坑经历
    最初只能处理单个 Excel 文件,扩展到多文件时:
    • 重复代码量大(每个文件写一次读取逻辑)
    • 数据合并时列名不统一导致错误
    • 无法追踪数据来源
  • 改进代码
    实现批量加载与标准化处理:

    python

    运行

    def load_multi_files(file_paths):all_data = []for path in file_paths:try:df = pd.read_excel(path)# 标准化处理df['source_file'] = os.path.basename(path)df['trade_date'] = pd.to_datetime(df['trade_date'])all_data.append(df)except Exception as e:print(f"加载{path}失败: {e}")return pd.concat(all_data, ignore_index=True)
    
  • 成长收获
    掌握批量数据处理模式,通过添加元数据(source_file)提升可追溯性。

五、答辩现场:坑的复现与解决方案演示

1. 现场复现:数据空值导致图表空白

  • 演示步骤
    1. 故意加载一个空数据文件
    2. 点击刷新按钮,图表显示 "数据为空" 提示
    3. 查看日志:validate_data函数捕获到空值异常
  • 解决方案代码

    python

    运行

    def plot_with_error_handling(data):try:valid_data = validate_data(data)# 正常绘图逻辑except ValueError:plt.text(0.5, 0.5, "无有效数据", ha='center', va='center')plt.axis('off')
    

2. 现场演示:多文件加载与异常处理

  • 演示内容
    1. 同时加载 3 个文件,其中 1 个文件格式错误
    2. 系统自动跳过错误文件,合并正常数据
    3. 日志显示:加载output3.xlsx失败: 列名不匹配
  • 关键代码展示

    python

    运行

    # 错误捕获与跳过
    except Exception as e:print(f"加载{path}失败: {e}")continue  # 跳过当前文件
    

六、评委提问:从踩坑到成长的深度思考

1. 提问:如何避免重复踩相同的坑?

  • 回答
    我建立了 "坑记录 - 复盘 - 预防" 机制:
    1. 每个坑都记录在 README 的 TROUBLESHOOTING 章节
    2. 复盘时提炼成可复用的代码片段(如数据校验函数)
    3. 新功能开发前先查阅历史坑记录,提前预防
      (展示项目中的.pitfalls.md文件,包含 12 个历史坑的解决方案)

2. 提问:踩坑过程中最大的技术认知转变是什么?

  • 回答
    最初认为 "代码能跑就行",但在踩过环境配置、数据空值等坑后,认识到:
    • 工程化代码需要 "防御性编程"(处处校验输入)
    • 系统设计要 "面向变化"(如函数式架构比类更灵活)
    • 错误处理不是 "附加功能",而是核心逻辑的一部分

七、总结:坑是成长的阶梯

从最初连图表都画不出来,到现在能处理多源数据并生成系统化分析报告,每一个坑都成为了成长的阶梯。这段经历让我深刻理解:

  • 技术成长 = 解决问题的积累:不是代码量的增加,而是处理异常场景能力的提升
  • 好代码是改出来的:从代码 1 到代码 2 的改进,不是推倒重来,而是每次踩坑后的针对性优化
  • 坑的价值在于被转化:将所有踩过的坑转化为代码中的校验逻辑、异常处理和文档说明,才是真正的成长

未来我将继续保持 "遇坑 - 析坑 - 填坑" 的习惯,让每一次问题都成为技术提升的契机。谢谢!

八、答辩后改进计划(基于坑的总结)

  1. 坑预防自动化
    开发pitfall_checker.py脚本,自动扫描代码中可能引发历史坑的模式
  2. 坑文档可视化
    .pitfalls.md转化为交互式流程图,直观展示坑的触发条件与解决方案
  3. 新人防坑指南
    为项目编写《新人避坑手册》,包含环境配置、数据处理等常见坑的一键解决方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/86976.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/86976.shtml
英文地址,请注明出处:http://en.pswp.cn/web/86976.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Python] -基础篇7-新手常见Python语法错误及解决方案

Python 以其简洁明了的语法引人入胜,但对于初学者而言,仍然容易遭遇各类语法错误。本文总结了 Python 语言日常编写中最常见的语法错误类型,并提供解决方案和正确写法,帮助新手快速突破编程路上的一道道埋伏。 1. 拼写错误 (SyntaxError) 这是最基本也最常见的错误类型。…

位运算实战:数值构造终极优化

位运算优化实战&#xff1a;数值构造问题详解 今天我们将深入分析一个有趣的位运算优化问题&#xff0c;这个问题展示了如何通过巧妙的预处理和贪心算法来高效解决数值构造问题。 问题背景与定义 给定一个初始值x&#xff08;0 ≤ x ≤ m&#xff09;和一系列位运算操作&…

nosql项目:基于 Redis 哨兵模式的鲜花预订配送系统

1 鲜花预订配送系统概述 1.1 项目背景 鲜花预订系统是一个实时处理用户订单、库存管理和配送跟踪的平台。系统需要处理大量并发订单&#xff0c;实时更新鲜花库存状态&#xff0c;并跟踪配送进度。传统关系型数据库难以应对高并发的订单处理和实时库存更新需求&#xff0c;因…

中心效应:多中心临床试验的关键考量

一、中心效应的来源与影响 1.1 常见来源 1.1.1 患者异质性 中心间基线特征差异(如疾病严重度、合并症比例) 1.1.2 操作差异 给药规范(如输液速度)、随访依从性、数据记录质量 1.1.3 评估偏倚 影像学判读标准(如RECIST)、实验室检测方法(如中心实验室 vs 本地实验室) …

Redis 实现消息队列

一、为什么选择 Redis 作为消息队列&#xff1f; 在分布式系统架构中&#xff0c;消息队列是实现异步通信和解耦的核心组件。Redis 作为一个高性能的内存数据库&#xff0c;凭借其卓越的速度和丰富的数据结构&#xff0c;成为轻量级消息队列的理想选择&#xff1a; 1.1 核心优…

(3)pytest的setup/teardown

1. 简介 学过unittest的都知道里面用前置和后置setup和teardown非常好用&#xff0c;在每次用例开始前和结束后都去执行一次。 当然还有更高级一点的setupClass和teardownClass&#xff0c;需配合classmethod装饰器一起使用&#xff0c;在做selenium自动化的时候&#xff0c;它…

Starrocks存算一体和存算分离

网上整理了一下starrocks两种部署方式的区别差异性&#xff0c;个人感觉生产环境还是尽量存算分离部署&#xff0c;防止资源争夺等问题影响线上生产数据&#xff0c;虽然存算一体部署起来更方便一些 &#x1f4ca; 1. 架构设计 存算一体&#xff1a; 节点类型&#xff1a;仅包含…

多线程编程 ----线程主动退出pthread_exit与线程被动退出pthread_cancel

主动退出 pthread_exit 与 pthread_cancel 的区别 1. 核心区别 特性pthread_exitpthread_cancel调用者线程自身调用&#xff0c;主动退出。其他线程调用&#xff0c;异步请求终止目标线程。行为方式立即终止线程&#xff0c;资源需手动释放。发送取消请求&#xff0c;线程在取…

电脑开机加速工具,优化启动项管理

软件介绍 今天为大家推荐一款专业的电脑启动项管理工具&#xff0c;这款软件能有效优化电脑开机速度&#xff0c;帮助用户管理开机自启动程序。 使用方式 软件无需安装&#xff0c;以管理员身份直接双击运行即可使用。为确保安全&#xff0c;软件特别设计为不添加注册表…

设备管理的11个指标、七大误区、六大特征

1、设备的完好率 在这些指标里用得最多,但其对管理的促进作用有限。所谓的完好率,是在检查期间,完好设备与设备总台数的比例(设备完好率=完好设备数/设备总数)很多工厂的指标可以达到95%以上。理由很简单,在检查的那一刻,如果设备是运转的,没出故障,就算是完好的,于…

11OAuth2

目录 本节大纲 一、OAuth2 简介 二、OAuth2 授权总体流程 三、四种授权模式 授权码模式 简化模式 密码模式 客户端模式 四、OAuth2 标准接口 五、GitHub 授权登录 1. 创建 OAuth 应用 2. 项目开发 六、Spring Security OAuth2 七、授权、资源服务器 1. 授权服务器…

Github Copilot协助解决cucumber插件不支持async/await

一、提示词 问题描述 在使用了badeball/cypress-cucumber-preprocessor插件后&#xff0c;存在不支持nodejs原生的promise和async/await语法问题 执行用例命令 npx cypress run --env configFilemhesi-staging,TAGS"API005" --spec "cypress/integration/AL…

C++多线程【Linux】

Linux的多线程 Linux的子线程实际上也是个进程&#xff0c;但是比传统的进程轻量化。 pthread pthread是用于Linux系统下的线程库&#xff0c;头文件是<pthread.h>。C11 之前的多线程开发高度依赖平台原生 API&#xff0c;Windows 以 CreateThread 和内核对象为核心&am…

Windows 环境下 NVM 命令详解:多版本 Node.js 管理利器

“一个 Node.js 版本走天下&#xff1f;太局限了&#xff01;试试 nvm&#xff0c;版本切换如丝般顺滑。” 什么是 NVM NVM&#xff08;Node Version Manager&#xff09;是一个命令行工具&#xff0c;允许你安装并在多个 Node.js 版本之间自由切换。 在 Linux/macOS 下常用的…

一二级路由之间的传参方式以及高亮问题

实现如下图所示的一二级路由的高亮情况&#xff1a; 在一级路由APP.vue下设置&#xff1a; .head a.router-link-active {background-color: rgb(235, 221, 204); }在二级路由Mycenter.vue下设置&#xff1a; /* 要求在点击跳转到mycenter_lianxi页面时候父路由保持高亮…

前端JavaScript力扣HOT100刷题【51-100】

注&#xff1a;纯手打&#xff0c;如有错误欢迎评论区交流&#xff01; 转载请注明出处&#xff1a;https://blog.csdn.net/testleaf/article/details/148953015 编写此文是为了更好地学习前端知识&#xff0c;如果损害了有关人的利益&#xff0c;请联系删除&#xff01; 本文章…

智能制造数字孪生集成交付生态链:智慧产线极速克隆,孪生重构生产周期

在智能制造的浪潮中&#xff0c;数字孪生技术正以前所未有的速度重塑制造业的生产模式。从产品设计到生产制造&#xff0c;再到运维管理&#xff0c;数字孪生通过构建物理世界的虚拟镜像&#xff0c;实现了生产全流程的数字化映射与优化。 山东融谷信息以“智能制造数字孪生集成…

非常详细版: dd.device.geolocation 钉钉微应用获取定位,移动端 PC端都操作,Vue实现钉钉微应用获取精准定位并渲染在地图组件上

dd.device.geolocation 钉钉微应用获取定位,钉钉微应用获取精准定位并渲染在地图组件上 ,手机端 PC端要都可用 【dd.device.geolocation是需要鉴权的哦】 想要的数据和效果图 想要的数据格式 代码 <template><div class="dialogStyles"

鸿蒙5:组件状态共享

目录 1. 组件状态共享 1.1 状态共享-父子传值&#xff1a;Local、Param、Event 1.2 状态共享-父子双向绑定!! 1.3 跨代共享&#xff1a;Provider和Consumer 1.3.1 aliasName和属性名 1.3.2 实现跨代共享 1.3.3 装饰复杂类型&#xff0c;配合Trace一起使用 1.3.4 支持共…

【MySQL】12. C语言与数据库的连接

1. 下载MySQL的连接库 sudo apt install -y libmysqlclient-dev 2. MySQL连接库的常用接口介绍 通过下面的样例了解MYSQL的常用接口&#xff1a; #include <iostream> #include <mysql/mysql.h> using namespace std;const char *host "localhost";…