自学教程 学编程从这里开始

Pandas 数据排序与聚合

排序用于调整数据展示顺序、辅助找极值;聚合用于分组统计,是报表、指标计算的核心。本文把 sort_values、sort_index、rank、groupby、agg、transform、apply 整合在一起,延续销售明细数据集。
前置导入

import pandas as pd
import numpy as np

一、示例数据

data = {
    "订单号": ["A001", "A002", "A003", "A004", "A005", "A006"],
    "商品": ["键盘", "鼠标", "显示器", "键盘", "鼠标", "显示器"],
    "数量": [2, 1, 1, 3, 2, 2],
    "单价": [89, 45, 1200, 89, 45, 1200],
    "下单日期": ["2026-10-01", "2026-10-02", "2026-10-03", "2026-10-04", "2026-10-04", "2026-10-05"]
}
df = pd.DataFrame(data)
df["金额"] = df["数量"] * df["单价"]

二、数据排序 sort_values

sort_values 按字段值排序,最常用

# 单列排序:按金额升序
df_sort1 = df.sort_values(by="金额", ascending=True)

# 多列排序:先按商品,同商品内按金额降序
df_sort2 = df.sort_values(by=["商品", "金额"], ascending=[True, False])

# 缺失值放最前面(na_position="last" 默认放末尾)
df_sort3 = df.sort_values(by="金额", na_position="first")

参数说明:

  • by:排序字段,支持列表多字段
  • ascending:布尔/布尔列表,对应每一列升降序
  • na_position:first / last,控制NaN位置
  • ignore_index=True:排序后重置行索引(非常推荐,避免索引乱掉)
# 推荐写法,排序后重置索引
df_sort = df.sort_values("金额", ascending=False, ignore_index=True)

三、索引排序 sort_index

按行索引或者列名排序

# 行索引升序
df.sort_index()
# 行索引降序
df.sort_index(ascending=False)
# 对列名排序(横向排列)
df.sort_index(axis=1)

四、排名 rank

排序的衍生功能,计算每条数据在组内的名次

# 金额排名
df["金额排名"] = df["金额"].rank(method="min", ascending=False)

method 选项:

  • min:并列取最小名次(1,2,2,4)
  • max:并列取最大名次(1,3,3,4)
  • average:并列取平均名次(默认,1,2.5,2.5,4)
  • first:值相同,按原始出现先后排名

五、基础聚合(不分组,全局统计)

直接对整个Series/DataFrame做聚合

# 单个统计
df["金额"].sum()
df["金额"].mean()
df["金额"].max()
df["金额"].min()
df["金额"].count()   # 非空数量
df["金额"].median()  # 中位数
df["金额"].std()     # 标准差

# 一次性多个聚合
df["金额"].agg(["sum", "mean", "max", "min"])

# 多列分别聚合
df[["数量","金额"]].agg(["sum","mean"])

六、groupby 分组 + agg 聚合(核心)

6.1 简单分组

# 按商品分组,金额求和
g = df.groupby("商品")
g["金额"].sum()

6.2 agg 多聚合,自定义结果列名(新版推荐)

agg_result = df.groupby("商品").agg(
    订单总数=("订单号", "count"),
    销售总数量=("数量", "sum"),
    销售总金额=("金额", "sum"),
    平均单价=("单价", "mean"),
    最大单笔金额=("金额", "max")
).reset_index()
print(agg_result)

reset_index() 把分组索引变回普通列,方便后续导出Excel

6.3 同一个字段,多个聚合函数

df.groupby("商品")["金额"].agg(["sum", "mean", "max"])

6.4 多字段分组

# 商品 + 日期双重分组
df.groupby(["商品", "下单日期"]).agg(总金额=("金额","sum")).reset_index()

6.5 as_index 参数

# as_index=False,分组结果直接是普通列,不用reset_index
df.groupby("商品", as_index=False).agg(总金额=("金额","sum"))

七、transform 分组聚合(结果回填到原表)

agg 输出分组汇总行;transform 会保持原DataFrame行数不变,把分组统计值回填到每一行(用来做组内对比)

# 每个商品的总金额,回填到原始每一行
df["商品总金额"] = df.groupby("商品")["金额"].transform("sum")
# 组内均值
df["商品平均金额"] = df.groupby("商品")["金额"].transform("mean")
# 计算单笔占本组总额比例
df["占比"] = df["金额"] / df["商品总金额"]

这个是报表里计算占比、组内排名高频用法。

八、filter 分组过滤(过滤整个分组)

和普通布尔筛选不一样:filter 是按分组整体过滤,满足条件的整个分组保留

# 只保留总金额大于1000的商品分组
df_filter = df.groupby("商品").filter(lambda x: x["金额"].sum() > 1000)

普通筛选:过滤行;filter:过滤整个分组

九、apply 在groupby内自定义聚合

适合复杂逻辑,性能弱,小数据集用

def group_stats(sub_df):
    return pd.Series({
        "总额": sub_df["金额"].sum(),
        "笔数": len(sub_df),
        "最大单": sub_df["金额"].max()
    })

df.groupby("商品").apply(group_stats)

十、排序 + 聚合 组合实战模板

# 1. 分组汇总
group_df = df.groupby("商品", as_index=False).agg(
    总数量=("数量","sum"),
    总金额=("金额","sum")
)
# 2. 按总金额降序排序
group_df = group_df.sort_values("总金额", ascending=False, ignore_index=True)
print(group_df)

十一、常用参数速记

方法作用特点
sort_values按值排序最常用,支持多列
sort_index按索引排序行/列索引
rank组内排名并列名次多种策略
agg分组汇总输出少行,统计报表
transform分组回填行数不变,用于对比、占比
filter分组筛选剔除整个分组,不是单行
apply自定义分组逻辑灵活,速度慢

十二、避坑清单

  1. 排序后索引混乱,记得加 ignore_index=True
  2. groupby 默认会把分组字段变成索引,不想用索引就 as_index=False 或者 reset_index()
  3. transform 必须保证返回的Series长度和分组子表一致,否则报错
  4. apply 适合复杂逻辑,大数据优先用向量化、transform、agg,不要滥用
  5. 多列排序时,ascending 列表长度必须和排序字段数量一致
  6. 字符串排序是字典序,数字字符串排序容易出错,先转数值

标签:

0 条笔记