你上传一份 5 万行的 CSV,问”所有行的平均营收”,ChatGPT 基于前 1000 行作答——总数明显是错的。最快的修法: 先确认它真的跑了 Python,再把 prompt 写成聚合请求、而不是汇总请求。上传后第一条消息直接贴这句:用 pandas 加载文件,打印 df.shape,然后计算我要的总数——把代码跑起来,不要采样。 只要 df.shape 对得上你真实的行数,后面每个数字就都可信。
同一个错误的总数背后有两种失败模式。普通对话(没跑 Python)里,ChatGPT 只把文件文本的一部分塞进 context,然后基于那一片做外推。**Code Interpreter / Advanced Data Analysis(ADA)**里文件完整落盘,但含糊的 prompt 会让模型只 print df.head() 再口述,根本没跑聚合。修法是:强制 pandas 在完整 DataFrame 上执行;文件接近沙箱内存上限时用 chunksize 分块;或者本地预聚合后只上传 rollup。
先判断你属于哪一类
| 对话记录里的现象 | 大概率原因 | 跳到 |
|---|---|---|
| 没有 Python / 分析工具跑过;行数特别整(1000、2000) | 普通对话采样了文件 | Step 1 + Step 2 |
代码 cell 里只有 df.head() / df.dtypes,从没 df.shape 或聚合 | ”汇总”类含糊 prompt | Step 2 |
MemoryError、“kernel restarted”,或悄悄加 nrows=1000 重试 | 撞沙箱内存上限(约 1 GB) | Step 3 / Step 4 |
跑完 chunksize 循环后,最终数字只反映一部分数据 | chunk 没累加 | Step 3 |
| 模型断言某些列”不存在” | 宽表显示被截断 | Step 1(打印 df.columns) |
常见原因
1. 普通对话只采样,不加载
没开 Code Interpreter 时,ChatGPT 读表格就是把文件文本的一部分塞进模型 context,再基于那一片推理。采样之外的所谓”分析”都是外推、不是计算。表格虽然不受 2M-token 文本上限约束,但这不代表每一行都进了 context——只要没跑 Python,模型用的还是预览片段。
如何判断:作答时没有 Python 工具图标,也没有 “Analyzing” 的代码 cell;报告的行数特别整(1000、2000)。
2. Code Interpreter 加载了,但只 print 了 df.head()
在 ADA 里 pandas 能整份读。但 prompt 含糊(“汇总这个文件”),模型默认就 print 前 5 行 + 列信息,再口述结论,从不跑 df.shape 或 df.describe()。
如何判断:代码 cell 里只有 df.head() 和 df.dtypes,没有 df.shape、没有任何聚合。文字里写 “based on the sample…“
3. 较大文件撞沙箱内存上限
Code Interpreter 沙箱内存大约 1 GB(截至 2026 年 6 月;在 ChatGPT app 内固定,无法调高)。单文件上传上限是 512 MB,而 CSV / Excel 实际只能到 约 50 MB,取决于行的宽度。即便文件本身能上传成功,pandas 一旦把它解析成 DataFrame 也可能超过 1 GB——字符串列在内存里会膨胀。这时 pd.read_csv 抛 MemoryError 或者 kernel restart,模型为了”让它能跑”经常自动加 nrows=1000 重试,然后把这个子集当答案。
如何判断:代码 trace 里出现 MemoryError、kernel restart,或失败后悄悄改用 nrows= 重读。
4. chunksize 累加遗漏
用 chunksize= 读但忘了跨 chunk 累加,最终答案只来自最后一块。自定义聚合 prompt 经常踩这个。
5. 列方向被显示截断
pd.set_option("display.max_columns") 默认很低。50 列的文件 print 中间是 ...,模型有时会断言那些被隐藏的列”不存在”。
最短修复路径
Step 1:先确认整份文件被加载了
每次都用一段 shape 检查开头,免得你在切片上推理:
import pandas as pd
df = pd.read_csv("/mnt/data/big.csv")
print("rows:", df.shape[0])
print("cols:", df.shape[1])
print("columns:", list(df.columns))
print("memory MB:", round(df.memory_usage(deep=True).sum() / 1e6, 1))
rows 对得上你预期,文件就完整加载了,后续聚合可信。打印 columns 顺手干掉原因 5——即便显示会隐藏,你也能看到全部列名。
Step 2:把 prompt 写成聚合请求,不是汇总请求
明确要求模型把代码跑起来:
用 pandas 加载 /mnt/data/big.csv,先打印 df.shape。
然后计算并打印实际数字,不要采样:
- df["revenue"].sum()
- df.groupby("region")["revenue"].sum()
- df["date"].min(), df["date"].max()
把 Python 跑起来;不要从 df.head() 口述结论。
ADA 会逐行执行,答案就是真值。“不要从 df.head() 口述”这句,是稳定堵住原因 2 的关键。
Step 3:较大文件用 chunksize 流式处理并累加
文件接近内存上限时,分块处理再累加——这能同时修原因 3 和原因 4:
import pandas as pd
total = 0
n = 0
for chunk in pd.read_csv("/mnt/data/huge.csv", chunksize=200_000):
total += chunk["revenue"].sum()
n += len(chunk)
print("rows processed:", n)
print("total revenue:", total)
对求和、计数、大多数 groupby 聚合都管用。要精确的百分位或中位数,得跨 chunk 保留 partial state(或者用下面的 DuckDB 方案)。打印出来的 rows processed 应该等于你的完整行数——不相等就说明丢了一块。
沙箱里更省内存的替代方案是 DuckDB,它从磁盘流式读取,从不把整份文件塞进 RAM:
import duckdb
duckdb.sql("""
SELECT region, sum(revenue) AS rev, count(*) AS rows
FROM '/mnt/data/huge.csv'
GROUP BY region
""").show()
Step 4:本地预聚合后再上传
内存吃紧、或只要 rollup 的,在你机器上先聚合,再上传那个小结果:
# 本地
import pandas as pd
df = pd.read_csv("huge.csv")
rollup = df.groupby(["region","quarter"]).agg(
rev_sum=("revenue","sum"),
rev_avg=("revenue","mean"),
rows=("revenue","count"),
).reset_index()
rollup.to_csv("rollup.csv", index=False)
上传 rollup.csv(几百行)。ChatGPT 立刻能分析,原始数据也不离开你机器。
Step 5:拆成 N 份分别分析
确实需要行级访问、但又装不下时,先拆:
split -l 100000 huge.csv part_
每次一份 + 一个问题;或者全放 Project 里让 ChatGPT 逐份迭代。文件数控制在 10 个以内,检索质量才稳——也别忘了配额:截至 2026 年 6 月,Plus 是每 3 小时滚动窗口 80 个文件,Free 大约每天 3 个,Team / Enterprise 是每 3 小时 160 个。
怎么确认已经修好了
- 对话里出现了 Python / 分析代码 cell(不只是文字)。
df.shape[0](或rows processed)等于你真实的行数。- 关键数字来自聚合行(
.sum()、.groupby()、DuckDB 的SELECT),不是来自df.head()。 - 把同一个总数再问一遍——正确的计算结果在重跑之间稳定不变;采样估计通常会漂。
预防
- 重复分析大数据,先在本地用 pandas 或 DuckDB 建管线,只把聚合结果上传。
- 上传时第一条 prompt 永远包含
df.shape+df.columns,亲眼验证整份文件加载成功。 - 文件 > 100 MB 优先用 Parquet 而不是 CSV——通常体积小 5-10 倍、读取更快、还保留 dtype(加载时字符串列不会撑内存)。
- 临时探索可以采样:
df.sample(10_000, random_state=42)——可复现的子集、任何 prompt 都装得下。 - 大屏 / 周期性报表用 Code Interpreter + 整份文件,但 prompt 永远写成明确的聚合,绝不写”汇总”。
常见问题
我文件有 5 万行,为什么 ChatGPT 说正好 1000 行?
因为根本没跑 Python。普通对话把文件的一片塞进 context,报的是那一片的大小。重问一句”跑 pandas 并打印 df.shape”,让行数来自真实的读取。
CSV 上传的实际文件大小上限是多少? 硬上限是单文件 512 MB,但 CSV / Excel 实际只能到约 50 MB(取决于行宽),而且解析后的 DataFrame 还得装进约 1 GB 的沙箱(截至 2026 年 6 月)。比这大就流式处理(Step 3)或本地预聚合(Step 4)。
能调高 Code Interpreter 的内存上限吗? 在 ChatGPT app 里不能——容器内存是固定的(约 1 GB)。更高的内存只能通过 OpenAI API 的 Code Interpreter 工具配置,消费端 app 不行。在 app 里,分块读取或 DuckDB 就是变通办法。
一个问题对了,下一个答案又错了,为什么? 每个新的分析轮次可能起一份全新的代码状态,含糊的追问(“现在按月拆”)又会触发采样。每次都把聚合明确重述一遍,或者把所有计算放进同一条 prompt。
分块文件上怎么拿到精确的中位数或 95 分位?
逐 chunk 的百分位没法合并成正确的全局值。要么只读你需要的那一列(pd.read_csv(path, usecols=["revenue"])),让内存里只住这一列;要么用 DuckDB 的 quantile_cont(revenue, 0.95),它能对整份文件算、又不用全部加载进 RAM。