学习 pandas 最有效的方式,不是背诵 API,而是走完一条完整的数据处理链路:从网页读取表格,确认数据结构,计算统计值,再把结果保存成 CSV。下面用一份公开的餐厅账单数据,把这些基础操作串起来。
从网页直接读取表格
如果网页提供的是 CSV 文件,可以把 URL 直接交给 pd.read_csv()。这种方式不需要先手动下载文件,适合公开数据集和自动化脚本。
运行前安装 pandas:
python -m pip install "pandas>=2.0"
将下面代码保存为 pandas_basics.py,然后运行 python pandas_basics.py:
from pathlib import Path
import pandas as pd
DATA_URL = (
"https://raw.githubusercontent.com/"
"mwaskom/seaborn-data/master/tips.csv"
)
OUTPUT_FILE = Path("output/tips_clean.csv")
# 1. 从网络读取 CSV
df = pd.read_csv(DATA_URL)
# 2. 验证后续计算需要的列
required_columns = {"total_bill", "tip", "day"}
missing_columns = required_columns - set(df.columns)
if missing_columns:
raise ValueError(f"缺少必要字段: {sorted(missing_columns)}")
# 3. 查看 DataFrame 的基本情况
print("前 5 行:")
print(df.head())
print("\n行数和列数:", df.shape)
print("\n字段类型:")
print(df.dtypes)
print("\n缺失值数量:")
print(df.isna().sum())
# 4. 清理参与计算的数据并创建新字段
clean = df.dropna(subset=["total_bill", "tip", "day"]).copy()
clean["tip_rate_pct"] = clean["tip"] / clean["total_bill"] * 100
# 5. 计算整体平均值
print(f"\n平均账单金额: {clean['total_bill'].mean():.2f}")
print(f"平均小费金额: {clean['tip'].mean():.2f}")
print(f"平均小费比例: {clean['tip_rate_pct'].mean():.2f}%")
# 6. 按星期分组计算平均值
average_by_day = (
clean.groupby("day", observed=True)
.agg(
average_bill=("total_bill", "mean"),
average_tip=("tip", "mean"),
records=("total_bill", "size"),
)
.round(2)
.sort_values("average_bill", ascending=False)
)
print("\n按星期统计:")
print(average_by_day)
# 7. 保存处理后的数据
OUTPUT_FILE.parent.mkdir(parents=True, exist_ok=True)
clean.to_csv(OUTPUT_FILE, index=False, encoding="utf-8")
print(f"\n已保存到: {OUTPUT_FILE.resolve()}")
这里使用 Path.mkdir() 创建输出目录,因此脚本不要求提前准备 output 文件夹。to_csv(..., index=False) 则避免把 DataFrame 的行索引写成一个额外字段。
探索 DataFrame 时该看什么
拿到一个陌生 DataFrame 后,不要立即计算平均值。至少先回答四个问题:
df.head():数据内容是否符合预期?df.shape:表格有多少行、多少列?df.dtypes:准备计算的字段真的是数值类型吗?df.isna().sum():缺失值会不会影响结果?
还可以用一条语句快速查看数值字段的分布:
print(df.describe())
describe() 会给出计数、均值、标准差、最小值、四分位数和最大值。它适合快速体检,但不能替代业务判断。例如,账单金额出现负数时,即使 pandas 仍能正常求平均值,也不代表结果可信。
平均值不只是调用 mean()
单列平均值很直接:
average_tip = df["tip"].mean()
pandas 默认会跳过缺失值。这通常很方便,但也可能隐藏数据质量问题。更稳妥的做法是同时输出有效记录数:
valid_tips = df["tip"].dropna()
print("有效记录数:", valid_tips.count())
print("平均小费:", valid_tips.mean())
分析分类数据时,分组平均值往往比整体平均值更有解释力:
result = df.groupby("day", observed=True)["tip"].mean().round(2)
print(result)
需要注意,平均值容易被极端值拉动。如果数据分布偏斜,可以同时检查中位数:
print(df[["total_bill", "tip"]].agg(["mean", "median"]))
网页是 HTML 表格时怎么办
如果数据不是 CSV,而是网页里的 <table>,可以使用 pd.read_html()。它返回的是 DataFrame 列表,因为一个页面可能包含多张表。
可以这样实践:
python -m pip install pandas lxml
import pandas as pd
url = "https://www.w3schools.com/html/html_tables.asp"
tables = pd.read_html(url)
print(f"找到 {len(tables)} 张表")
first_table = tables[0]
print(first_table.head())
first_table.to_csv("html_table.csv", index=False)
实际项目中不要默认 tables[0] 永远是目标表。网页结构可能变化,最好检查列名,或者使用 match= 参数按表格内容筛选。
上手时的检查清单
一条可靠的 pandas 基础处理链路通常包括:
- 确认输入是 CSV、JSON 还是 HTML 表格,选择对应的读取函数。
- 用
head()、shape、dtypes和缺失值统计检查数据。 - 在计算前验证必要字段,并明确如何处理空值和异常值。
- 同时观察整体平均值、分组平均值和中位数。
- 导出 CSV 时明确是否保留索引,并指定合适的编码。
- 网络数据可能变更或暂时不可访问;生产任务应增加超时、重试、缓存和字段校验。
掌握这些操作后,pandas 就不再只是零散函数的集合,而是一条可以重复执行、检查并交付结果的数据处理流程。