示例驱动的数据清洗:用脏数据+干净样本反向生成清洗代码
1. 项目概述当人类把“脏数据”和“理想结果”同时甩给AI会发生什么我最近在帮一家本地社区健康中心整理十年来的居民体检记录拿到手的Excel文件简直像被猫抓过的毛线团——列名有中文、英文、拼音缩写混着来日期格式从“2023/05/12”到“12-May-2023”再到“20230512”空值用“N/A”“NULL”“—”“空白格”“#N/A”六种方式轮着出现血压字段里还混着“120/80 mmHg”“120/80”“120,80”甚至“高压120低压80”这样的自由发挥体。更绝的是同一份表里前100行是标准格式第101行开始突然多出一列“备注新”而最后200行又悄悄删掉了“身高”列。这种数据别说建模Excel自带的“删除重复项”都报错。就在我准备手动清洗第三天、咖啡因摄入量突破安全阈值时我干了一件看似偷懒实则关键的事我把这份“原始脏数据”和我自己花两小时手工整理出来的“干净版本”一起扔进了ChatGPT的Code Interpreter现在叫Advanced Data Analysis里只问了一句“请分析这两份数据的差异并告诉我如何用代码自动复现我的清洗逻辑。”结果它不仅准确识别出了所有清洗动作还生成了可复用、带注释、能处理未来同类数据的Python脚本。这件事让我意识到我们过去总在教AI“怎么清洗”而这次我们直接把“问题”和“答案”并排摆上桌让AI自己反向推导出那套隐性的、经验性的、甚至带点直觉的清洗规则。这不再是单向指令而是一次双向校准——人类提供语义意图与质量锚点AI提供可执行路径与泛化能力。核心关键词就是脏数据、干净样本、反向工程清洗逻辑、Code Interpreter、数据清洗自动化、示例驱动编程。如果你也常被杂乱无章的业务数据折磨既不想写几百行硬编码规则又不敢全盘交给黑盒模型瞎猜那这个思路就是为你量身定制的它不取代你的判断力而是把你脑子里那些“我觉得这里该填均值”“这个缩写明显是‘体重’”的瞬间直觉翻译成机器能听懂、能复用、能迭代的语言。它适合数据分析师、业务运营、科研助理、甚至需要处理问卷或爬虫数据的产品经理——只要你每天要和Excel、CSV打交道哪怕只会复制粘贴也能立刻上手。2. 核心思路拆解为什么“给答案比给指令”更高效2.1 传统数据清洗的三大死循环在讲清楚这个方法之前得先说说我们平时是怎么把自己绕进去的。我见过太多人卡在三个经典陷阱里每个都耗时耗力还容易返工。第一个是“规则先行”的幻觉。比如看到“血压”列里有“120/80 mmHg”第一反应是写个正则表达式r(\d)/(\d)\s*mmHg。听起来很专业对吧但现实是你刚写完隔壁同事发来的新批次数据里“血压”列变成了“BP: 120/80”再下一批又成了“Systolic/Diastolic: 120/80”。你写的正则只能匹配一种模式而业务数据的混乱是无限的。我试过维护一个包含17种血压格式的正则库结果第三个月就发现第18种格式——“120 over 80”——直接让整个清洗流程崩掉。这不是技术问题是认知问题我们误以为数据混乱是“异常”其实它是常态我们想用确定性规则去覆盖不确定性注定失败。第二个是“试错调试”的泥潭。很多人会打开Pandas写一行df[date] pd.to_datetime(df[date])运行报错看错误信息查文档改参数再运行……如此循环几十次。我统计过自己一个中等复杂度的清洗任务平均要经历43次“运行-报错-修改”循环其中68%的错误源于对原始数据分布的误判——比如以为“年龄”全是数字结果第5001行突然冒出个“未知”或者以为“性别”只有“男”“女”结果第8922行来了个“M/F”。每次报错都是在用真实数据打脸你之前的假设。这个过程极其消耗心力而且无法沉淀——下一次遇到新数据一切重来。第三个是“知识孤岛”的困境。最资深的数据工程师写的清洗脚本往往只在他自己的电脑上跑得通。因为里面嵌了太多“只有我知道”的上下文比如他记得第37列的“ID”其实是患者身份证号后六位所以做了特殊截取或者他发现“费用”列里的“120.00”和“120元”必须统一成浮点数但“免费”要转成0这个逻辑没写进注释只存在他脑子里。当项目交接或数据源变更这套脚本就成了天书。我接手过一个医疗数据项目前任留下的清洗代码有213行其中47行是硬编码的列索引和特殊值替换没有任何注释。我花了整整两天才搞懂其中一行df.iloc[:, 12] df.iloc[:, 12].str.replace(N/A, 0).fillna(0)的真实意图——原来第12列是“自费金额”而“N/A”在这里代表“医保全额报销”所以填0是对的。但这个业务含义代码里一个字都没提。2.2 “双样本输入”如何一举击穿这三个死结当我把“脏数据”和“干净数据”同时喂给Code Interpreter时本质上是在做一件非常聪明的事把人类的领域知识clean version和AI的模式识别能力dirty version强制对齐。这就像教一个新员工不是给他一本《数据清洗操作手册》而是直接带他看“清洗前的原始表格”和“清洗后的最终表格”然后问“你觉得中间发生了什么”——而Code Interpreter就是那个观察力极强、记忆力超群、还能立刻写出操作步骤的新员工。它的优势体现在三个层面第一层是语义理解的升维。Code Interpreter看到的不是孤立的字符串而是两个结构化对象之间的映射关系。它会自动计算原始表有12列干净表有10列那么必然有2列被删除或合并原始表某列有37%的空值干净表对应列空值为0%说明做了填充原始表某列值域是[男,女,M,F,Male,Female]干净表统一为[M,F]说明做了标准化映射。这些结论不需要你写任何规则AI通过对比就能推断出来。我做过测试给它一份含5种日期格式的脏数据和一份统一为ISO格式的干净数据它生成的代码里dateutil.parser.parse()调用前自动加了try...except捕获所有可能的解析异常并为每种异常类型指定了fallback策略——这比我自己写鲁棒性代码还周全。第二层是逻辑可追溯的闭环。生成的每一行代码都能在两个样本间找到明确的对应证据。比如它生成df[blood_pressure_systolic] df[BP].str.extract(r(\d)/\d).astype(float)你立刻能回溯到干净表里“收缩压”列的值和脏表“BP”列中匹配(\d)/\d模式的那些行。如果某行结果不对你不用猜直接查那行原始数据和干净数据就能定位是AI理解错了还是原始数据本身有歧义。这种“所见即所得”的调试体验彻底终结了“为什么这行没变”的灵魂拷问。第三层是知识沉淀的自动化。最终生成的脚本天然就是一份带执行痕迹的说明书。它不再是你脑子里的模糊记忆而是白纸黑字的、可版本控制的、可被任何人复用的资产。更重要的是这个脚本是“活”的——当你下次拿到新数据只要把新脏数据和旧干净数据或新干净数据再喂一遍AI就能告诉你哪些清洗逻辑依然有效哪些需要微调。我把它叫做“清洗逻辑的持续集成”它让数据治理从一次性劳动变成了可持续演进的工程实践。2.3 这不是魔法而是有严格前提的“精密手术”当然这个方法不是万能钥匙它有清晰的适用边界和成功前提忽略这些效果会大打折扣。前提一干净样本必须是“高质量锚点”而非“完美幻象”。很多人犯的致命错误是把干净数据做得过于理想化。比如原始数据里“地址”列有大量“北京市朝阳区建国路8号”和“北京朝阳建国路8号”你手工清洗时为了“整洁”全统一成“北京市朝阳区建国路8号”。但Code Interpreter看到这个变化会推断出“必须补全所有省市区三级行政单位”结果在处理“上海市徐汇区”时强行加上“上海市徐汇区上海市”造成新错误。正确的做法是干净样本应忠实反映你真实的业务决策。如果“北京朝阳建国路8号”在业务系统里就是合法地址那干净样本里就该保留它。干净样本的价值在于它定义了“什么是可接受的”而不是“什么是数学上最完美的”。我给自己定的铁律是干净样本里的每一处修改都必须能在原始数据里找到明确的、唯一的、无歧义的对应依据。前提二脏数据与干净数据必须严格一一对应。行顺序不能变列名可以不同但行内容必须是同一实体。我曾因疏忽把干净数据按姓名排序了而脏数据是按录入时间排序结果AI生成的代码里充满了基于行号的错误索引。Code Interpreter没有“实体对齐”能力它默认第1行对第1行第2行对第2行。所以操作前务必确认len(dirty_df) len(clean_df)且dirty_df.iloc[0][patient_id] clean_df.iloc[0][patient_id]用唯一标识符验证。一个简单但无比有效的技巧是在导入后立即添加一列row_id range(len(df))清洗完成后再删掉。这行代码成本几乎为零却能避免90%的对齐灾难。前提三你必须是那个“最终拍板人”而非“甩手掌柜”。AI生成的代码永远是初稿。它可能过度泛化比如把所有含“/”的字符串都当成血压处理也可能欠拟合比如只处理了最常见的3种空值漏了第4种。我的工作流是先让它生成然后逐行审阅重点看三类代码1所有str.contains()、str.extract()等字符串操作检查正则是否太宽或太窄2所有fillna()、dropna()确认填充策略是否符合业务逻辑比如“年龄”空值填均值合理但“诊断结果”空值填“未确诊”就危险3所有列名映射确保没有张冠李戴。这个审阅过程通常只需15分钟但它把AI的“可能性”转化为了你可控的“确定性”。3. 实操全过程从上传文件到生成可复用脚本的每一步3.1 环境准备与数据预处理别让细节毁掉好主意在Code Interpreter里开工前有三个看似微小、实则决定成败的准备工作我建议你像检查手术器械一样认真对待。第一步文件格式与编码的“静默杀手”排查。我吃过太多亏了。有一次客户发来一个UTF-8编码的CSV但Excel默认用ANSI打开我复制粘贴时中文全变成了乱码再保存回去文件就变成了GBK编码。当我把这份“看起来一样”的文件丢给Code Interpreter它读取时用UTF-8解码结果所有中文列名都变成b\xe5\xa7\x93\xe5\x90\x8d这样的字节串后续所有操作全崩。解决方案极其简单粗暴在本地用VS Code或Notepad打开原始文件右下角看编码格式如果是ANSI或GBK立刻另存为UTF-8无BOM。对于Excel文件同样重要务必确认是.xlsx而不是.xls老版本二进制格式Code Interpreter支持不稳定。我现在的标准动作是收到文件先用file命令Mac/Linux或在线工具Windows检查真实编码再用Pandas的pd.read_csv(filepath, encodingutf-8)在本地试读确保列名和前几行数据正常显示最后才上传。第二步原始数据的“快照式”探查。绝对不要跳过这一步。我创建了一个固定的探查模板每次必跑import pandas as pd df pd.read_csv(dirty_data.csv) print( 数据概览 ) print(f形状: {df.shape}) print(f内存使用: {df.memory_usage(deepTrue).sum() / 1024**2:.2f} MB) print(\n 列信息 ) print(df.info()) print(\n 缺失值统计 ) print(df.isnull().sum().sort_values(ascendingFalse)) print(\n 前5行 ) print(df.head()) print(\n 各列唯一值示例最多5个) for col in df.columns: print(f{col}: {df[col].dropna().unique()[:5]})这个脚本输出的信息远比肉眼扫一眼Excel有价值。它会立刻暴露某列看似是数字实则混有字符串info()显示object类型某列缺失值高达95%但你之前以为只有5%某列的“唯一值”里赫然出现N/A和nan并存——这说明缺失值有多种表示法清洗时必须一并处理。我曾靠这个脚本在上传前就发现“联系电话”列里有12个“暂无”、8个“-”、3个“未提供”这直接决定了我后续fillna()策略的复杂度。第三步干净样本的“最小必要修饰”。干净数据不是越“干净”越好而是越“真实”越好。我的原则是只做业务必需的修改不做美学修饰。具体操作绝不重排序保持与脏数据完全一致的行序。绝不删行即使脏数据里有明显重复或错误行干净数据里也要保留只是把错误值修正。因为AI需要学习“如何修正”而不是“如何删除”。列名可优化但需谨慎如果脏数据列名是“xingming”干净数据可以改成“name”但不能改成“full_name”——除非业务上真有“first_name”和“last_name”之分。列名变更必须有明确的业务依据且最好在列名旁加注释如name (original: xingming)。数值精度保持一致如果脏数据里“体重”是65.0干净数据里就别写成65否则AI可能误判为整型转换。做完这三步你手里就有了两份“可信”的数据可以放心上传了。记住Code Interpreter的“智能”建立在输入数据的“诚实”之上。你糊弄它它就会用更精巧的方式糊弄你。3.2 Code Interpreter交互如何提问才能得到最精准的代码上传完两个文件真正的艺术开始了如何向AI提问决定了你得到的是废柴脚本还是生产级武器。我经过上百次实验总结出一套高成功率的提问公式。基础公式[角色] [任务] [约束] [期望输出][角色]明确AI的身份。不要说“帮我写代码”要说“你是一位有10年医疗数据治理经验的数据工程师”。这会激活AI更专业的知识库。[任务]清晰描述核心目标。“分析dirty_data.csv和clean_data.csv之间的差异并生成一个能将任意类似dirty_data.csv格式的数据自动转换为clean_data.csv格式的Python脚本。”[约束]设定硬性边界。这是最关键的一步必须包含使用pandas和numpy不使用其他第三方库。所有字符串操作必须使用正则表达式且正则需有详细注释说明匹配逻辑。对缺失值的处理必须明确写出填充策略如均值、众数、固定值及其业务依据。生成的脚本必须包含完整的错误处理try/except并打印清晰的错误日志。[期望输出]指定交付物。“输出一个完整的、可直接运行的.py文件包含详细的中文注释注释需解释每一行代码的业务含义而不仅是技术含义。”一个实战中的完美提问示例你是一位专注基层医疗信息化的数据治理专家。请严格分析我上传的community_health_dirty.csv原始社区体检数据和community_health_clean.csv我手工清洗后的标准数据之间的所有差异。目标是生成一个健壮的Python清洗脚本能将未来任何同源的community_health_dirty.csv格式数据自动转换为community_health_clean.csv格式。约束1仅使用pandas、numpy、re2所有正则表达式必须有注释说明其匹配的业务场景例如“匹配‘120/80 mmHg’、‘120/80’等血压常见格式”3对‘年龄’列的缺失值用该列非空值的中位数填充业务依据年龄分布近似正态中位数抗异常值4对‘诊断结果’列的缺失值统一填充为‘未评估’业务依据未做该项检查非数据丢失5脚本必须包含try/except块捕获并打印所有可能的异常类型及原始错误信息。请输出一个完整的、带详细中文注释的.py文件。看到这个提问你就知道为什么它有效了它把AI的“自由发挥”框死在了业务规则里。我对比过用这个公式提问生成脚本的首次可用率从32%提升到了89%。关键在于约束部分不是技术限制而是把你的业务知识翻译成AI能执行的指令。交互中的黄金法则一次只问一个问题但要问透。不要试图让AI“先分析差异再生成代码再写测试用例”。Code Interpreter的上下文窗口有限多任务会导致它顾此失彼。我的标准流程是第一轮只问“请详细列出两份数据的所有差异按列、按行、按值域分类”。让AI先交一份“差异分析报告”。我仔细阅读确认它没漏掉任何关键点比如它可能没注意到“日期”列里有5种格式但只报告了3种。如果有遗漏就追问“请重点检查‘date_of_exam’列列出所有不同的日期字符串格式及其出现频次。”第二轮基于确认无误的差异报告再问“请根据以上差异生成清洗脚本”。这时AI已经建立了完整的上下文生成的代码质量会高得多。第三轮可选针对脚本中的某一行要求解释或优化。比如看到df[bp_systolic] df[BP].str.extract(r(\d{2,3})/\d{2,3})我会问“这个正则是否会错误匹配‘1200/80’错误的四位数收缩压请优化以确保第一位数字是1或2。” AI会立刻给出更严谨的r(1\d{2}|2[0-9]{2})/\d{2,3}。这种分步、聚焦、可验证的交互才是人机协作的正确打开方式。3.3 核心清洗逻辑生成与代码详解看AI如何“读懂”你的意图当AI返回脚本时别急着复制粘贴。我把它当作一份需要深度解读的“技术合同”逐行拆解理解AI的每一个决策背后的业务逻辑。下面我以一个真实的血压清洗案例带你走一遍这个过程。原始脏数据中“BP”列的典型值120/80 mmHg 130/85 BP: 110/75 Systolic/Diastolic: 140/90 120,80 高压120低压80干净数据中对应的“bp_systolic”和“bp_diastolic”两列120, 80 130, 85 110, 75 140, 90 120, 80 120, 80AI生成的核心代码段如下# 血压列清洗从自由文本中提取收缩压和舒张压 # 步骤1统一列名为BP便于后续操作 if BP not in dirty_df.columns: # 尝试匹配常见列名变体血压、blood_pressure、B.P.等 bp_candidates [血压, blood_pressure, B.P., BP_Value, pressure] found_col None for cand in bp_candidates: if cand in dirty_df.columns: found_col cand break if found_col: dirty_df dirty_df.rename(columns{found_col: BP}) else: raise ValueError(未在原始数据中找到血压相关列请检查列名) # 步骤2创建临时列标准化所有血压字符串为统一格式 # 业务依据原始数据中血压表达方式多样需先归一化再提取 dirty_df[BP_normalized] dirty_df[BP].astype(str).str.strip() # 替换常见前缀和后缀 dirty_df[BP_normalized] dirty_df[BP_normalized].str.replace(r^.*?(\d/\d).*?$, r\1, regexTrue) # 匹配xxx120/80xxx - 120/80 dirty_df[BP_normalized] dirty_df[BP_normalized].str.replace(r^(?:BP|血压|高压|Systolic).*?(\d/\d).*?$, r\1, regexTrue) # 匹配BP: 120/80 - 120/80 dirty_df[BP_normalized] dirty_df[BP_normalized].str.replace(r(\d),(\d), r\1/\2, regexTrue) # 匹配120,80 - 120/80 dirty_df[BP_normalized] dirty_df[BP_normalized].str.replace(r高压(\d)低压(\d), r\1/\2, regexTrue) # 匹配高压120低压80 - 120/80 # 步骤3安全提取收缩压和舒张压 # 使用更严格的正则确保数值在合理医学范围内 # 收缩压90-250 mmHg舒张压60-150 mmHg systolic_pattern r^(1[0-9]{2}|2[0-4][0-9]|250)/(\d{2,3})$ diastolic_pattern r^(\d{2,3})/(1[0-9]{2}|2[0-4][0-9]|250)$ # 提取收缩压匹配120/80中的120 dirty_df[bp_systolic] dirty_df[BP_normalized].str.extract(systolic_pattern, expandFalse)[0] # 提取舒张压匹配120/80中的80 dirty_df[bp_diastolic] dirty_df[BP_normalized].str.extract(diastolic_pattern, expandFalse)[1] # 步骤4数据类型转换与异常处理 # 将提取结果转为数值无效值设为NaN dirty_df[bp_systolic] pd.to_numeric(dirty_df[bp_systolic], errorscoerce) dirty_df[bp_diastolic] pd.to_numeric(dirty_df[bp_diastolic], errorscoerce) # 步骤5业务逻辑校验与填充 # 业务依据若收缩压或舒张压为空且原始BP列有值则尝试用均值填充作为兜底 # 但此处优先保留原始逻辑干净数据中无填充故保持NaN后续由主流程统一处理这段代码的价值远不止于功能实现。它是一份活的、可执行的业务知识文档。我们来逐层解剖第一层命名规范与容错设计。它没有假设列名一定是“BP”而是主动搜索了6种常见变体。这背后是我的经验在10家社区卫生中心的数据里“血压”列名平均有3.2种写法。AI把这个经验转化成了bp_candidates列表和循环查找逻辑。if BP not in ...的判断不是技术冗余而是对现实世界不确定性的尊重。第二层归一化思维。它没有试图用一个超级正则匹配所有格式而是分三步走先用正则剥离无关字符再用正则替换常见变体最后统一为X/Y格式。这模仿了人类专家的思考路径——先“去噪”再“标准化”最后“提取”。str.replace(..., regexTrue)里的正则每一个都附带了清晰的业务注释告诉你它在解决哪个具体问题。第三层医学合理性校验。systolic_pattern正则里的1[0-9]{2}|2[0-4][0-9]|250不是随便写的。它精确覆盖了临床公认的收缩压合理范围90-250 mmHg。1[0-9]{2}匹配100-1992[0-4][0-9]匹配200-249250是上限。这行代码把教科书上的医学知识直接编译进了数据清洗逻辑里。如果原始数据里有“300/200”它会被这个正则过滤掉不会污染后续分析——这就是AI在帮你守门。第四层错误处理的哲学。errorscoerce参数意味着遇到无法转换的字符串如“未知”、“--”不是报错中断而是优雅地设为NaN。这体现了对数据现实的深刻理解清洗不是追求100%完美而是追求100%可控。所有不可信的数据都被标记为NaN后续你可以用业务规则统一处理而不是让脚本在第5001行崩溃。第五层注释即文档。每一行注释都在回答“为什么这么做”。# 业务依据若收缩压或舒张压为空...这句不是技术说明而是把你的决策理由固化在了代码里。半年后当新同事接手他不需要问你看注释就能明白为什么这里不填充而那里要填充。这就是“示例驱动”的力量你提供的干净样本不仅告诉AI“结果长什么样”更通过它的结构、值域、缺失模式无声地传递了“为什么长这样”的全部业务逻辑。AI做的只是把这些隐性的“为什么”翻译成了显性的、可执行的“怎么做”。3.4 脚本的落地与验证让代码真正跑起来生成的脚本只是万里长征第一步。真正的价值在于它能否在真实环境中稳定、可靠、可维护地运行。我的验证流程分为三关缺一不可。第一关单元测试——用“已知答案”检验“未知代码”。我会从原始脏数据中手动抽取10-20行最具代表性的“困难户”组成一个微型测试集。比如行1标准格式120/80 mmHg行2带前缀BP: 130/85行3逗号分隔120,80行4中文描述高压120低压80行5异常值300/200应被过滤行6空值NaN行7混合格式Systolic/Diastolic: 140/90 mmHg然后我写一个极简的测试脚本test_data pd.DataFrame({ BP: [120/80 mmHg, BP: 130/85, 120,80, 高压120低压80, 300/200, None, Systolic/Diastolic: 140/90 mmHg] }) # 导入并运行生成的清洗函数 from generated_cleaner import clean_bp_column result clean_bp_column(test_data) print(result)运行后我逐行核对输出确保每一行都符合干净样本的预期。这一关的目的不是证明代码“能跑”而是证明它“跑得对”。如果某一行错了我就把这一行单独拎出来喂给Code Interpreter问“为什么对高压120低压80你的脚本输出了120和None”——这往往能暴露出正则的边界漏洞。第二关回归测试——用“历史数据”检验“未来兼容性”。这是最体现工程素养的一关。我会找一份上周清洗过的、已经上线使用的干净数据以及它对应的上周原始脏数据。然后用新生成的脚本去清洗上周的脏数据再和上周的干净数据做df.equals()比对。如果100%匹配说明新脚本完全兼容历史逻辑如果有差异就必须深挖是新脚本更优修复了历史bug还是新脚本有误引入了新bug我曾经发现新脚本对“血压”列的处理比旧脚本多了一步“剔除异常值”导致上周某行数据从140/90变成了NaN。这触发了我的警报这个“异常值”判定是否过于激进我立刻回溯业务规则确认了“300/200”是异常但“140/90”是高血压前期属于有效数据。于是我调整了正则的数值范围把收缩压上限从250放宽到260。这个过程让脚本从“能用”进化到了“可信”。第三关压力测试——用“海量数据”检验“真实性能”。Code Interpreter生成的代码往往在小数据上飞快但在大数据上可能慢如蜗牛。我有一份50万行的模拟体检数据专门用来压测。关键指标有两个内存峰值用memory_profiler库监控确保脚本不会因copy()或apply()操作导致内存爆炸。AI有时会生成df[new_col] df.apply(lambda x: some_heavy_func(x), axis1)这在50万行上会吃光8GB内存。我的应对是把它重构为向量化操作或用swifter库加速。执行时间记录从读取到输出的总耗时。如果超过5分钟就需要优化。常见瓶颈是复杂的正则匹配或多重str.replace()。我的优化策略是用re.compile()预编译正则或把多个replace()合并为一个replace({a:x, b:y})。通过这三关验证的脚本我才敢把它放进生产环境。它不再是一个“可能有用”的玩具而是一个经过千锤百炼、能扛住真实业务压力的可靠组件。4. 常见问题与独家避坑指南那些只有踩过才知道的坑4.1 “AI生成的代码为什么和我想要的不一样”——理解AI的“认知偏差”这个问题我被问得最多。答案往往不是AI错了而是你和AI的“认知坐标系”没对齐。Code Interpreter是一个强大的模式匹配引擎但它没有“常识”只有“统计规律”。它所有的“理解”都来自你提供的两个样本之间的统计关联。所以当结果偏离预期首先要检查的是你的输入样本。坑一干净样本里藏着“幽灵逻辑”。我曾给AI一份干净数据其中“诊断结果”列我把所有“糖尿病”都统一写成了“Diabetes”但忘了把“2型糖尿病”也改成“Diabetes”。AI看到脏数据里有“2型糖尿病”干净数据里对应行是“Diabetes”它就推断出“所有含‘糖尿病’的字符串都应标准化为‘Diabetes’”。这逻辑没错但它不知道“1型糖尿病”和“2型糖尿病”在临床上是不同亚型。结果脚本把“1型糖尿病”也粗暴地改成了“Diabetes”丢失了关键信息。避坑心得在准备干净样本时用Excel的“条件格式”高亮所有你做了“语义合并”的地方比如把“2型糖尿病”、“T2DM”、“Type II Diabetes”都标成黄色然后在旁边加一列merge_reason写明“业务上视为同一诊断”。这样你在审阅AI生成的代码时就能立刻定位到str.replace()那一行判断它是否过度泛化。坑二脏数据里的“沉默异常值”。AI擅长处理“显性混乱”比如乱七八糟的列名、五花八门的空值。但它对“沉默的异常值”束手无策。比如“年龄”列里99%的值是18-90的整数但有3个值是180、200、