科普:pandas 中的类 SQL语句:transaction.groupby(“card_id“)[‘purchase_day‘].diff()

python 复制代码
transaction['purchase_day_diff'] = transaction.groupby("card_id")['purchase_day'].diff()

等价于 SQL 里的窗口函数:

sql 复制代码
SELECT 
    card_id,
    purchase_day,
    -- 按用户分组,按时间排序,取上一行的 purchase_day,即LAG使时间滞后一步(后移一格),反之,LEAD = 超前一步(前移一格)
    LAG(purchase_day) OVER (PARTITION BY card_id ORDER BY purchase_day) AS prev_day,
    -- 当前天 - 上一天 = 时间差
    purchase_day - LAG(purchase_day) OVER (PARTITION BY card_id ORDER BY purchase_day) AS purchase_day_diff
FROM transaction

一、该python语句等价于 SQL 里的窗口函数

groupby(列).diff() = SQL 的 LAG() 窗口函数,算组内行与行的差值!

1、实现功能

按每个用户分组,把他的交易按时间排序,然后算:当前交易日期 - 上一次交易日期 = 间隔天数


假设交易表:

card_id purchase_day
user1 10
user1 15
user1 20
user2 5
user2 9

执行:

python 复制代码
groupby("card_id")['purchase_day'].diff()

得到:

card_id purchase_day purchase_day_diff
user1 10 NaN(第一笔,没有上一笔)
user1 15 5(15-10)
user1 20 5(20-15)
user2 5 NaN
user2 9 4(9-5)

2、对应 SQL

运行结果一模一样

sql 复制代码
SELECT
    card_id,
    purchase_day,
    purchase_day - LAG(purchase_day) OVER(PARTITION BY card_id ORDER BY purchase_day) AS purchase_day_diff
FROM transaction

结果:

card_id purchase_day purchase_day_diff
user1 10 NULL
user1 15 5
user1 20 5
user2 5 NULL
user2 9 4

这里的窗口函数做了什么?

  1. 按用户分窗口:OVER(PARTITION BY)
  2. 排序:ORDER BY
  3. LAG 取上一行:LAG(purchase_day)
  4. 手动减法 = diff:purchase_day - LAG(purchase_day)

二、SQL的窗口函数

前面提到SQL的窗口函数,这里专门讲讲。

窗口函数 = 对一组内行与行之间互相计算,但不把多行压成一行(保留原行数)

对比:

  • GROUP BY:多行 → 一行(汇总)
  • 窗口函数:多行 → 还是多行(行与行之间计算)

1、普通聚合(GROUP BY)------压扁

sql 复制代码
SELECT card_id, SUM(amount) FROM transaction GROUP BY card_id

结果:一个用户一行

2、窗口函数 ------不压扁,每行都保留

sql 复制代码
SELECT card_id, SUM(amount) OVER (PARTITION BY card_id)

结果:多少行,还是多少行,但每一行都带上了该用户的总和


窗口函数结构(固定格式)

sql 复制代码
函数() OVER (
    PARTITION BY 列1, 列2   -- 分组(窗口)
    ORDER BY 排序列         -- 组内排序
)

三部分:

  1. OVER:标志这是窗口函数
  2. PARTITION BY:把数据分成多个小组(窗口)
  3. ORDER BY:组内按什么顺序排

方式 结果行数 作用
GROUP BY 减少(每组1行) 汇总统计
窗口函数 不变(原行数) 行与行之间计算

三、其它类似的对应关系

1、核心对应规则

python 复制代码
df.groupby(分组列)[统计列].聚合函数()

完全等价 SQL:

sql 复制代码
SELECT 分组列, 聚合函数(统计列)
FROM df
GROUP BY 分组列

2、 对应举例

1)groupby + sum

python 复制代码
transaction.groupby("card_id")["purchase_amount"].sum()

SQL:

sql 复制代码
SELECT card_id, SUM(purchase_amount)
FROM transaction
GROUP BY card_id

含义:每个用户总消费金额


2)groupby + mean

python 复制代码
transaction.groupby("card_id")["purchase_amount"].mean()

SQL:

sql 复制代码
SELECT card_id, AVG(purchase_amount)
FROM transaction
GROUP BY card_id

含义:每个用户平均消费金额


3)groupby + count

python 复制代码
transaction.groupby("card_id")["purchase_amount"].count()

SQL:

sql 复制代码
SELECT card_id, COUNT(purchase_amount)
FROM transaction
GROUP BY card_id

含义:每个用户有多少笔交易(非空)


4)groupby + size

python 复制代码
transaction.groupby("card_id").size()

SQL:

sql 复制代码
SELECT card_id, COUNT(*)
FROM transaction
GROUP BY card_id

含义:每个用户总交易笔数(不管空值)


5)groupby + nunique(去重计数)

python 复制代码
transaction.groupby("card_id")["merchant_category_id"].nunique()

SQL:

sql 复制代码
SELECT card_id, COUNT(DISTINCT merchant_category_id)
FROM transaction
GROUP BY card_id

含义:每个用户消费过多少个不同商户类别


6)groupby + min / max

python 复制代码
transaction.groupby("card_id")["purchase_amount"].min()
transaction.groupby("card_id")["purchase_amount"].max()

SQL:

sql 复制代码
SELECT card_id, MIN(purchase_amount), MAX(purchase_amount)
FROM transaction
GROUP BY card_id

7)groupby + diff(本文开头提到的)

python 复制代码
transaction.groupby("card_id")["purchase_day"].diff()

SQL:

sql 复制代码
purchase_day - LAG(purchase_day) OVER (PARTITION BY card_id ORDER BY purchase_day)

3、多列聚合(pandas agg → SQL GROUP BY 多函数)

python 复制代码
transaction.groupby("card_id").agg({
    "purchase_amount": ["sum", "mean", "max"],
    "merchant_id": "nunique",
    "card_id": "size"
})

对应 SQL:

sql 复制代码
SELECT
    card_id,
    SUM(purchase_amount),
    AVG(purchase_amount),
    MAX(purchase_amount),
    COUNT(DISTINCT merchant_id),
    COUNT(*)
FROM transaction
GROUP BY card_id

4、它们是包pandas的API功能

上述提到的这些函数 全部属于 pandas

python 复制代码
groupby()
sum()
mean()
count()
size()
nunique()
min()
max()
diff()
agg()

👉 全部是 pandas.DataFrame / pandas.Series 的方法

你必须导入 pandas 才能用

python 复制代码
import pandas as pd

没有这句,上面所有函数都不存在

它们是 pandas 自己实现的数据分析 API ,语法风格模仿 SQL,但底层是 pandas。


附:取行、取列、新建列

回到开头的这句代码:

python 复制代码
transaction['purchase_day_diff'] = transaction['purchase_day']...

左侧的中括号中是字符串!!

在交易表 transaction 里,新建一列 ,名字叫 purchase_day_diff

然后把右边计算好的"时间差"数据存进去。

pandas 设计就是:
中括号里写字符串 = 操作列
中括号里写数字 = 操作行


中括号里写字符串:右边取列,左边建列!

左边(等号左边)

python 复制代码
transaction['purchase_day_diff'] =...

新建一列 ,名字叫 purchase_day_diff

右边(等号右边)

python 复制代码
...= transaction['purchase_day']...

取出 purchase_day 这一列 用来计算


相关推荐
benchmark_cc18 小时前
如何用 Python + QuantDash 快速构建高胜率“配对交易(Pairs Trading)”策略?
开发语言·人工智能·python·pandas·量化交易·quantdash
踏月的造梦星球18 小时前
DMDPC 学习:架构、部署、运维与调优
运维·数据库·学习·架构
韩楚风18 小时前
【参天引擎】事务生命周期 / MVCC / Undo / ACID / 分布式事务 功能域整体解析
数据库·分布式·mysql·架构·cantian
renhongxia119 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
程序员无隅19 小时前
Coding Agent 为什么压缩上下文后还能继续工作?上下文模块设计拆解
java·开发语言·数据库
愿做无知一猿19 小时前
Nacos连接MySQL异常?DataGrip竟成救星
数据库·mysql
G.O.G.O.G19 小时前
LeetCode SQL 从入门到精通(MySQL)06(上)
数据库·sql·mysql·leetcode
研究员子楚20 小时前
GEO行业发展标准体系白皮书V2.0-第10卷 · 全球篇:跨国标准协同与全球品牌语义治理框架
数据库·人工智能·microsoft·架构·geo
Omics Pro21 小时前
深度学习多组学互作:组内+组间
数据库·人工智能·深度学习·mysql·搜索引擎·自然语言处理
残*影1 天前
如何优雅地保存MySQL数据变更历史?
数据库·mysql