将Pandas代码封装为函数后DataFrame变空的问题排查
问题分析与解决方案
核心问题点
- 未执行数据解析逻辑:仅调用了
get_file_and_format函数,但未调用parse_data,导致后续数据填充逻辑完全未运行。 - 循环逻辑错误:原代码中
p的计算逻辑冗余,每次循环都会重置为0,仅能处理第一行数据,大部分数据未被正确处理。 - 全局变量依赖:直接全局读取文件的方式不利于PySimpleGUI集成,应让函数接收文件路径参数,适配GUI选择文件的场景。
- 拼写错误:原代码中
dtype={'MemberIdentifer': int}存在拼写错误,应为MemberIdentifier,这可能是导致数据读取为空的隐藏原因。
修正后的代码
重构后的核心处理函数
import pandas as pd import PySimpleGUI as sg pd.set_option('mode.chained_assignment', None) def get_file_and_format(file_path): # 从传入路径读取文件,避免全局变量依赖 df = pd.read_csv(file_path, sep=',', dtype={'MemberIdentifier': int}) # 筛选需要的列 df = df[['MemberIdentifier', 'FirstName', 'LastName', 'BirthDate', 'Zip', 'HireDate', 'MedicalPlan', 'Division', 'GenderCode', 'EmailAddress']] # 批量添加新列,语法更简洁 df = df.assign( Region=str(), Role=str(), Company=str(), Action=str(), PrimaryMemberEmployeeId=str(), PrimaryMemberEmail=str() ) # 重命名列 df.rename(columns={ 'MemberIdentifier': 'EmployeeId', 'BirthDate': 'DateOfBirth', 'Division': 'Location', 'GenderCode': 'Gender', 'Zip': 'ZipCode', 'EmailAddress': 'Email' }, inplace=True) # 重新排列列顺序 df = df.reindex(columns=[ 'FirstName', 'LastName', 'Location', 'EmployeeId', 'DateOfBirth', 'Gender', 'ZipCode', 'Email', 'Role', 'PrimaryMemberEmail', 'PrimaryMemberEmployeeId', 'HireDate', 'Company', 'Action', 'MedicalPlan' ]) return df def parse_data(df): # 用条件赋值替代错误循环,高效处理Role列 df.loc[df['MedicalPlan'] == 'XXX Health Plan', 'Role'] = 'Employee On Plan' # 填充PrimaryMemberEmail字段 df['PrimaryMemberEmail'] = df['PrimaryMemberEmployeeId'].map( df.set_index('EmployeeId')['Email'] ).fillna(df['PrimaryMemberEmail']) # 填充Company字段 df['Company'].fillna('XXX', inplace=True) return df
集成PySimpleGUI的交互逻辑
# 构建GUI界面布局 layout = [ [sg.Text("选择待处理的CSV文件:")], [sg.Input(key="-INPUT_FILE-"), sg.FileBrowse(file_types=(("CSV文件", "*.csv"),))], [sg.Text("选择保存目录:")], [sg.Input(key="-SAVE_DIR-"), sg.FolderBrowse()], [sg.Button("开始处理"), sg.Button("退出")] ] window = sg.Window("CSV数据处理工具", layout) while True: event, values = window.read() if event == sg.WIN_CLOSED or event == "退出": break if event == "开始处理": input_file = values["-INPUT_FILE-"] save_dir = values["-SAVE_DIR-"] if not input_file or not save_dir: sg.popup("请选择完整的输入文件和保存路径!") continue # 执行数据处理流程 try: formatted_df = get_file_and_format(input_file) processed_df = parse_data(formatted_df) save_path = f"{save_dir}/XXX_company.csv" processed_df.to_csv(save_path, header=True, index=False) sg.popup(f"处理完成!文件已保存至:{save_path}") except Exception as e: sg.popup(f"处理出错:{str(e)}") window.close()
额外优化说明
- 用
df.assign()替代逐个添加列的方式,代码更简洁且避免潜在的链式赋值问题。 - 用
df.loc条件赋值替代低效的循环,大幅提升处理效率,同时避免索引操作错误。 - 所有函数均返回处理后的DataFrame,保证数据传递的完整性,符合函数式编程规范。
内容的提问来源于stack exchange,提问作者Pongotan
相关产品推荐
相关产品推荐

