用一份在线账单数据练熟 pandas:读取、检查、导出与求平均值

2026-09-18 27 预计阅读时间: 1 分钟
来源: realpython.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:7 分钟

学习 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()shapedtypes 和缺失值统计检查数据。
  • 在计算前验证必要字段,并明确如何处理空值和异常值。
  • 同时观察整体平均值、分组平均值和中位数。
  • 导出 CSV 时明确是否保留索引,并指定合适的编码。
  • 网络数据可能变更或暂时不可访问;生产任务应增加超时、重试、缓存和字段校验。

掌握这些操作后,pandas 就不再只是零散函数的集合,而是一条可以重复执行、检查并交付结果的数据处理流程。


相关推荐