
本文详解如何使用 OML4Py 的 oml.group_apply 对 Oracle Machine Learning 数据代理对象按两个字段联合分组,并执行自定义聚合逻辑,替代 SQL 中 GROUP BY col1, col2 的功能。
本文详解如何使用 oml4py 的 `oml.group_apply` 对 oracle machine learning 数据代理对象按两个字段联合分组,并执行自定义聚合逻辑,替代 sql 中 `group by col1, col2` 的功能。
在 OML4Py 中,oml.group_apply 是执行分布式分组聚合的核心接口,但其分组机制不同于 SQL —— 它不接受字符串形式的列名列表,而是通过 index 参数传入一个包含分组键的 OML 数据代理(如 DF[:, ['mgr', 'deptno']]),该代理将作为分组依据自动切分数据块并分发至 Python 函数处理。
要实现类似 SQL GROUP BY mgr, deptno 的效果(例如统计每个经理-部门组合下的记录数、部门编号出现次数等),关键在于两步:
- 构造复合分组索引:使用切片语法指定两个分组列,返回一个二维 OML proxy;
- 编写兼容的聚合函数:函数接收每个分组的 Pandas DataFrame 子集,需明确提取分组键值并返回结构化结果。
以下为完整示例(以 emp 表结构类比):
%python
# 定义聚合函数:返回 mgr、deptno、该组合记录数、deptno 出现频次(即 count(deptno))
def group_agg(dat):
import pandas as pd
if dat.empty:
return pd.DataFrame(columns=["mgr", "deptno", "count_mgr", "count_deptno"])
# 提取分组键(因 index 已含 mgr 和 deptno,故取首行值即可代表本组)
mgr_val = dat["mgr"].iloc[0] if "mgr" in dat.columns else None
deptno_val = dat["deptno"].iloc[0] if "deptno" in dat.columns else None
# 计算聚合指标
count_mgr = dat["mgr"].count() # 非空 mgr 数量(等价于 COUNT(mgr))
count_deptno = dat["deptno"].count() # 非空 deptno 数量(等价于 COUNT(deptno))
return pd.DataFrame([[mgr_val, deptno_val, count_mgr, count_deptno]],
columns=["mgr", "deptno", "count_mgr", "count_deptno"])
# 构建双列分组索引(注意:必须是 oml proxy,非字符串列表)
index_proxy = oml_emp[:, ["mgr", "deptno"]]
# 执行分组应用
result = oml.group_apply(
oml_emp,
index=index_proxy,
func=group_agg,
oml_input_type="pandas.DataFrame"
)
# 查看结果(自动按分组键排序,如需 ORDER BY deptno,后续可用 .sort_values("deptno"))
print(result.head())
⚠️ 重要注意事项:
- index 参数必须为 OML 数据代理(如 DF[:, ['col_a', 'col_b']]),不可传入 ['col_a', 'col_b'] 字符串列表,否则会报错;
- 分组函数 func 的输入 dat 是 Pandas DataFrame,但其索引不保留原始分组键,因此需从 dat 中显式提取(如 dat["mgr"].iloc[0]);
- 若原始表存在 NULL 值,COUNT(col) 在 SQL 中忽略 NULL,对应 Python 中应使用 .count()(而非 len()),因其仅统计非空值;
- oml.group_apply 返回结果默认按分组键字典序排序,若需特定顺序(如 ORDER BY deptno),应在返回后调用 result.sort_values("deptno")。
通过此方式,OML4Py 可高效复现多列 GROUP BY + 聚合的分析逻辑,同时充分利用 Oracle Database 内核的并行计算能力与 Python 的灵活数据处理优势。











