to_excel 一次只能写一张表,要写多张必须走 ExcelWriter。 index=False 几乎每次都要加,否则表里多出一列没有名字的序号。 日期必须是 datetime 类型,是字符串就排不了序、算不了间隔、画不了时间轴。
算完的东西得交出去。这一篇讲两件事:怎么导出、日期怎么处理。 日期单列一篇是有原因的:它是数据分析里最容易出错、也最容易被忽略的一块。
一、导出到一张表
df.to_excel('导出.xlsx', index=False, sheet_name='成绩'),一行写完。
这次写出去 5807 字节,读回来形状还是 (10, 6),一个字节都没丢。
index=False 几乎每次都要加。忘了他,Excel 里会多出一列没名字的序号。
那一列在别人手里就是个麻烦:删了怕有问题,不删又多一列。 sheet_name 不给就是 Sheet1。给人看的文件,表名取清楚点。
二、一个文件多张表:ExcelWriter
with pd.ExcelWriter(路径) as w: 然后在里面连续 to_excel(w, sheet_name=...)。
这次写出 3 张表:成绩、班主任、班级均值。读回来 sheet_name=None 拿到 3 个键。
to_excel 一次只能写一张表。要写多张必须走 ExcelWriter。
老办法是先写一张再 mode='a' 追加,麻烦还容易覆盖。用 with 最省心。
上下文管理器退出时自动保存并关闭。不 close 的文件是 0 字节——这条老账要记住。
三、转成日期:to_datetime
pd.to_datetime(['2026-01-05', '2026/1/6', '20260107'], format='mixed')。
三种写法都能认,得到 2026-01-05、01-06、01-07,类型是 datetime64[us]。
pandas 3 要显式写 format='mixed' 才能混着猜,不写会报错。
中文日期它不认:「2026年1月8日」直接 DateParseError,得自己换成 2026-1-8。 这一步很常见:从网页或 Word 里拷出来的日期,十有八九带「年月日」。
四、取出年月日与间隔
| 日期 | 年 | 月 | 星期 |
|---|---|---|---|
| 2026-01-05 | 2026 | 1 | 0 |
| 2026-01-06 | 2026 | 1 | 1 |
| 2026-01-07 | 2026 | 1 | 2 |
.dt 是日期专用的入口,year、month、day、hour 都挂在它下面。
星期用 day_of_week,周一是 0。老写法 dayofweek 还能用,但会报废弃警告。
两个日期一减得到 Timedelta:2 days 00:00:00。
日期减日期给的是「时间差」,不是数字。要天数写 .days,要秒写 .total_seconds()。
五、动手 Demo:数据导出与日期处理
先导一张表、再导三张表到一个文件,然后处理三种格式的日期。 最后取出年月日,算两个日期差。
import os
import pandas as pd
D = pd.DataFrame({"姓名": ["张伟", "王芳"], "语文": [88, 92]})
D.to_excel("导出.xlsx", index=False, sheet_name="成绩")
print("字节 %d,读回 %s" % (os.path.getsize("导出.xlsx"),
pd.read_excel("导出.xlsx").shape))
with pd.ExcelWriter("多表.xlsx") as w:
D.to_excel(w, sheet_name="成绩", index=False)
D.to_excel(w, sheet_name="备份", index=False)
print("多表:%s" % list(pd.read_excel("多表.xlsx", sheet_name=None).keys()))
DT = pd.to_datetime(["2026-01-05", "2026/1/6", "20260107"], format="mixed")
print("日期 %s" % [str(v)[:10] for v in DT])
print("类型 %s" % DT.dtype)
T = pd.DataFrame({"日期": DT})
T["年"] = T["日期"].dt.year
T["星期"] = T["日期"].dt.day_of_week
print(T.to_string(index=False))
print("间隔 %s,共 %d 天" % (DT[2] - DT[0], (DT[2] - DT[0]).days))
实跑输出:
--------------------------------------------------------------------
数据导出与日期处理
--------------------------------------------------------------------
① 导出到一张表
--------------------------------------------------------------------
写出去 5807 字节,读回来 (10, 6)。
index=False 是不写行号。不写这一条,Excel 里会多出一列没有名字的序号。
! index=False 几乎每次都要加。忘了它,别人打开就看到一列莫名其妙的 0、1、2。
② 一个文件多张表:ExcelWriter
--------------------------------------------------------------------
一个文件里 3 张表:成绩、班主任、班级均值。
用 ExcelWriter 上下文管理器,写多张表只需要一个文件句柄。
! to_excel 一次只能写一张表。要写多张,必须走 ExcelWriter。
③ 转成日期:to_datetime
--------------------------------------------------------------------
三种写法都能认:2026-01-05、2026-01-06、2026-01-07。
pandas 3 要显式写 format='mixed' 才能混着猜,不然会报错。
类型是 datetime64[us],不是字符串。
中文日期它不认:「2026年1月8日」直接报 DateParseError。
先换成 2026-1-8 这样的写法,再读就好了:2026-01-08。
! 日期读进来必须是 datetime 类型。是字符串就排不了序、算不了间隔、画不了时间轴。
④ 取出年月日与间隔
--------------------------------------------------------------------
| 行 | 日期 | 年 | 月 | 星期 |
|---|---:|---:|---:|---:|
| 0 | 2026-01-05 00:00:00 | 2026 | 1 | 0 |
| 1 | 2026-01-06 00:00:00 | 2026 | 1 | 1 |
| 2 | 2026-01-07 00:00:00 | 2026 | 1 | 2 |
.dt 是「日期专用」的入口,year/month/day/hour 都挂在它下面。
星期用的是 day_of_week,周一是 0。老写法 dayofweek 还能用,但会报 DeprecationWarning。
两个日期一减得到 Timedelta:2 days 00:00:00。
要天数就 .days,要秒数就 .total_seconds()。
! 日期减日期给的是「时间差」,不是数字。直接拿去算会报类型错。
字节数每次可能差几个字节(Excel 里存时间戳),形状 (2, 2) 才是要核的东西。
(DT[2] - DT[0]).days 给整数,直接拿 Timedelta 去算是会报错的。
30 秒实验
- 把 to_excel 的 index=False 去掉,再读回来看看多没多一列。
- 把 format='mixed' 去掉,看报什么错。
- 想一想:把日期当字符串存进 Excel,别人再读回来会是什么类型?
常见误区
- 忘了 index=False:文件里多一列没名字的序号。
- 一张一张 to_excel 想写进同一文件:后一次把前一次覆盖了。
- to_datetime 不写 format='mixed':格式一混就报错。
- 中文日期直接喂进去:DateParseError,得先清洗。
自测三问(点开对答案)
1. 为什么要用 ExcelWriter? —— to_excel 一次只能写一张表。要一个文件装多张,必须靠 ExcelWriter 统一管理。 2. 日期读进来是字符串会有什么后果? —— 排不了序(按字典序排)、算不了间隔、画不了时间轴、resample 直接报错。 3. Timedelta 怎么取出天数? —— 加 .days 取整天数,.total_seconds() 取秒数。直接拿去算会报类型错。最后一篇:把日期当索引,按周按月汇总,这就是时间序列。
- ☐ (本篇完,下一篇 4.14 时间序列与两个综合案例)