孔子曰:“勿意,勿必,勿固,勿我。学而不思则罔,思而不学则殆。”
此python脚本会从sales_data(Excel文件目录)的子目录(existing,new)中读取 Excel 文件、汇总数据,最后将总结表写入一个新的 Excel 文件。你可以在 VS Code 等软件中编写运行脚本。如果你想自己创建这个脚本,那么一定要将它和 sales_data (Excel文件目录)文件夹放到一起,这样就可以直接运行脚本而不用修改文件路径了。
代码如下:
from pathlib import Path
import pandas as pd
# 文件的目录
this_dir = Path(__file__).resolve().parent ➊
……
❶ 不仅能通过字符串来指定文件路径,还可以通过标准库 pathlib 模块中的 Path 类,你可以使用多种强大的工具:路径对象可以让你轻松地通过斜杠连接路径的分量来构造路径,就像在下方代码 this_dir / "sales_data" 及其下面几行代码中所展示的那样。这些路径对象是可以跨平台工作的,你也可以使用 rglob 之类的过滤器(下一点中会解释)。
__file__ 表示源代码文件运行时所在路径——因此 parent 返回的是脚本文件所在的目录。
在 parent 前面调用的 resolve 方法会将路径转换为绝对路径。
如果你想在 Jupyter 笔记本中运行这段脚本,那么需要将这行代码替换成 this_dir = Path(".").resolve(),用点来表示当前目录。在大部分时候,接受字符串形式的路径作为参数的函数和类也可以接受一个路径对象。
……
# 从sales_data的所有子文件夹中读取Excel文件
parts = []
for path in (this_dir / "sales_data").rglob("*.xls*"): ➋
……
❷ 读取某个目录中所有 Excel 文件的最简单办法就是使用路径对象的 rglob 方法。glob 是 globbing 的缩写,指的是通过通配符来展开路径名。? 通配符表示某单个字符,而 * 表示任意多个字符(包括 0 个)。rglob 中的 r 表示 recursive(递归)globbing,也就是说 rglob 会对所有子目录也进行匹配——相对的,glob 会忽略子目录。将 *.xls* 作为 globbing 表达式可以确保新旧两种格式的 Excel 文件都能被发现,因为这个表达式可以匹配 .xls 和 .xlsx 两者中的任意一种。
还可以稍微改进一下这个表达式,把它写成 [!~$]*.xls*。这样就可以忽略临时的 Excel 文件(文件名以~ $ 开头)。有关如何在 Python 中进行 globbing,请参见 Python 文档。
……
print(f'Reading {path.name}')
part = pd.read_excel(path, index_col="transaction_id")
parts.append(part)
# 将从Excel文件生成的DataFrame结合成单个DataFrame,
# pandas会负责对列进行对齐
df = pd.concat(parts)
# 对每个营业厅进行数据透视,将同一天产生的交易全部加起来
pivot = pd.pivot_table(df,
index="transaction_date", columns="store",
values="amount", aggfunc="sum")
# 按月重采样,并赋予一个索引名称
summary = pivot.resample("ME").sum()
summary.index.name = "Month"
# 将总结报表写入Excel文件
summary.to_excel(this_dir / "sales_report_pandas.xlsx")
运行脚本,你可以直接点击 VS Code 右上方的运行文件按钮。脚本会执行一段时间,VSC“终端”显示“Reading……”一系列代码,在完成之后,名为 sales_report_pandas.xlsx 的 Excel 工作簿就会出现在脚本所在的目录。
对于像这样简单的案例来说,pandas 为处理 Excel 文件提供了一种相当简单的解决方案。不过还可以更进一步,毕竟像设置标题、进行一些格式调整(包括列宽和定长位数的小数)、画个图,这些都不难。还可直接使用 pandas 的写入库来完成这些工作。
再小的个体,也有自己的目标。