前言
对刚接触 Python 的人来说,最实用的第一个脚本往往是"读一个 Excel、做点统计、 再输出结果"。pandas 让这件事变得很短:读进来是一个DataFrame, 之后的行列操作都围绕它展开。
不过有两件事要先交代。第一,pandas 是第三方库,读.xlsx还需要一个引擎, 通常是openpyxl,所以要pip install pandas openpyxl。 第二,本文的运行环境里没有 Python 解释器、没有 pandas,示例无法运行验证, 只能逐行人工推演。参数细节以 Pandas 官方文档为准。
一、读进来,先看清楚
# pandas 1.0+;需 pip install pandas openpyxl
import pandas as pd
df = pd.read_excel("sales.xlsx", sheet_name=0) # 默认读第一个工作表
print(df.shape) # (行数, 列数)
print(df.columns) # 列名
print(df.head()) # 前 5 行几个"看一眼"的入口,入门阶段务必先都过一遍:
| 方法 | 作用 |
|---|
df.shape | 行列数 |
df.head(n)/df.tail(n) | 前/后 n 行 |
df.columns | 列名列表 |
df.dtypes | 每列类型 |
df.info() | 行列数、类型、非空个数 |
df.describe() | 数值列的统计摘要 |
df.info()特别值得先看:它一次告诉你每列有多少非空值,缺失情况一目了然。df.describe()默认只统计数值列,给出计数、均值、标准差、最小最大值和四分位数, 传include="all"还能把类别列也一并统计进来。
注意read_excel的参数名是sheet_name(不是旧版的sheetname)。 一个 Excel 有多个工作表时,可传表名,或传sheet_name=None一次读全部并得到字典。
二、挑出你关心的行和列
# pandas 1.0+
df["金额"] # 取一列,返回 Series
df[["城市", "金额"]] # 取多列,返回 DataFrame
df[df["金额"] > 1000] # 按条件筛行
df.loc[df["城市"] == "北京", "金额"] # 按条件取某列要点:
- 取一列用单方括号,得到
Series;取多列要写双层方括号。 - 条件筛选用布尔序列,多个条件用
&、|连接,且每个条件都要加括号,
因为位运算符的优先级高于比较运算符。
- 按标签取值用
.loc,按位置取值用.iloc。前者按行/列的名字,后者按
从 0 开始的序号,且.iloc的切片不含结束位置——和 Python 列表一致。
# pandas 1.0+
subset = df[(df["金额"] > 1000) & (df["城市"] == "北京")]三、做几个常用统计
# pandas 1.0+
print(df["金额"].sum()) # 合计
print(df["金额"].mean()) # 平均
print(df["城市"].value_counts()) # 每个城市出现次数
print(df.sort_values("金额", ascending=False).head(10)) # 金额前 10value_counts()用来数类别频次特别好用,返回的是"值—次数"的Series, 默认按次数从多到少排。sort_values按某列排序,ascending=False表示降序。
Excel 里最常见的情况是"某一列有空单元格"。pandas 把它读成缺失值, 先用下面两行摸清情况再决定怎么处理:
# pandas 1.0+
print(df.isna().sum()) # 每列缺了多少个
print(df.isna().mean()) # 每列缺失的比例isna()返回布尔矩阵,.sum()数个数、.mean()算比例。 判定缺失只能用isna()/notna(),不要用== None或== numpy.nan: 因为浮点缺失值NaN连自己都不等于自己,==永远筛不出来。
四、简单分组汇总
# pandas 1.0+
by_city = df.groupby("城市", as_index=False)["金额"].sum()
print(by_city)groupby("城市")["金额"].sum()的含义是"按城市分组后对金额求和"。 默认分组键会变成结果的索引,加as_index=False可让它保持为普通列, 后续写 Excel 时更省心。
分组这一步很容易和另外两个操作搞混,这里顺手分清:
| 想做的事 | 该用的方法 |
|---|
| 按城市算总额 | groupby("城市")["金额"].sum() |
| 按城市和月份两个维度 | groupby(["城市", "月份"])["金额"].sum() |
| 去重 | df.drop_duplicates() |
| 改列名 | df.rename(columns={"旧": "新"}) |
drop_duplicates()默认按整行判断重复;只想按某几列去重,传subset=["城市"]。
五、结果写出去
# pandas 1.0+
by_city.to_excel("城市汇总.xlsx", index=False)index=False避免把行号也写进文件。若要在同一个 Excel 里放多张表, 用pd.ExcelWriter作为上下文管理器,给每次to_excel传不同的sheet_name。 写多个表时务必用with,否则文件可能没被正确保存:
# pandas 1.0+
with pd.ExcelWriter("结果.xlsx", engine="openpyxl") as writer:
by_city.to_excel(writer, sheet_name="按城市", index=False)
df.head(50).to_excel(writer, sheet_name="样例", index=False)关于类型,还有一点新手常问:为什么读进来的编号是1001,做一次筛选后就 变成了1001.0?原因是那一列里存在空单元格,pandas 为了让缺失值有位置可放, 把整列从int64提升成了float64。想让整数仍是整数,可以先把缺失填上, 或改用可空整数类型Int64。
六、一个完整的入门脚本
# pandas 1.0+;需 pip install pandas openpyxl
import pandas as pd
def analyze(path: str) -> pd.DataFrame:
df = pd.read_excel(path, sheet_name=0)
# 1) 先看清结构
print(df.shape)
print(df.info())
print(df.describe())
# 2) 处理一下空值:数值列按 0 填
df["金额"] = df["金额"].fillna(0)
# 3) 按城市汇总并降序排列
result = (
df.groupby("城市", as_index=False)
.agg(总额=("金额", "sum"), 笔数=("金额", "size"))
.sort_values("总额", ascending=False)
)
return result
if __name__ == "__main__":
summary = analyze("sales.xlsx")
print(summary)
summary.to_excel("城市汇总.xlsx", index=False)常见坑点
- 读 Excel 忘了装引擎
❌ 只pip install pandas就pd.read_excel("a.xlsx"),报缺少 openpyxl ✅ 先pip install openpyxl(写.xlsx同样需要它)
- 参数名写成旧版的
sheetname
❌pd.read_excel("a.xlsx", sheetname="Sheet1")✅pd.read_excel("a.xlsx", sheet_name="Sheet1")
- 取多列只写一层方括号
❌df["城市", "金额"],被当成一个元组键,直接 KeyError ✅df[["城市", "金额"]],双层方括号才是多列
- 多条件筛选忘了加括号
❌df[df["金额"] > 1000 & df["城市"] == "北京"], 位运算优先级导致逻辑错乱甚至报错 ✅df[(df["金额"] > 1000) & (df["城市"] == "北京")]
- 整数列有空值后变成小数
❌ 金额列里有个空单元格,整列变float64,整数显示成3.0✅ 这是正常现象;先fillna(0)或用dtype="Int64"
groupby后按列名取不到分组键
❌result["城市"]报 KeyError,因为城市变成了索引 ✅ 加as_index=False,或事后reset_index()
- 写 Excel 时行号也写进去了
❌ 结果表第一列多出一列 0,1,2 的索引 ✅to_excel("out.xlsx", index=False)
总结
| 阶段 | 常用方法 |
|---|
| 读取 | read_excel(sheet_name=) |
| 看数据 | shape/head/info/describe |
| 选取 | df[[...]]、布尔筛选、loc/iloc |
| 统计 | sum/mean/value_counts/sort_values |
| 汇总 | groupby(...).agg(...) |
| 输出 | to_excel(index=False) |
入门阶段记住一个顺序就够了:先看(shape/info/describe)→ 再选(筛选、取列) → 后算(统计、分组)→ 最后写(to_excel)。把这条链路跑顺, 再逐步学缺失值处理和合并,就水到渠成了。