DuckDB 新增统计扩展:17种假设检验
数据分析师有一个很烦的日常:SQL 里做了聚合,要跑个 t 检验就得把数据导到 R 或 Python,然后再导回来。来回倒腾,几千万行的表每次都要传一遍。
stats_duck 要解决的就是这件事。
一个 DuckDB 社区扩展,刚被收入 community-extensions。做的事很简单:把统计计算直接搬到 DuckDB SQL 里。t 检验、ANOVA、卡方、OLS 回归、甚至 SAS 文件读写,全都在 SQL 里完成,数据不需要离开数据库。
目前版本 v0.7.0,Apache 2.0 许可,由 Massimo Meneghello(GitHub: caerbannogwhite)维护。
● ● ●
它能做什么
打开 DuckDB,装扩展:
INSTALL stats_duck FROM community; LOAD stats_duck;
然后你可以在 SQL 里做这些事:
假设检验——全部是聚合函数
-- 两组独立样本 t 检验(Welch's) SELECT ttest_2samp(treatment, control) FROM experiment_results; -- 单因素方差分析 SELECT anova_oneway(value, group_name) FROM measurements; -- Mann-Whitney U(非参数,数据不正态也能用) SELECT mann_whitney_u(group_a, group_b) FROM non_normal_data;
总共 17 种检验:t 检验(单样本/双样本/配对)、ANOVA、卡方(独立性/拟合优度)、Mann-Whitney、Wilcoxon、Kolmogorov-Smirnov、Shapiro-Wilk、Jarque-Bera、Anderson-Darling 等等。
每个检验返回一个 STRUCT,包含检验统计量、自由度、p 值、效应量、置信区间。比如 t 检验的结果里有 t_statistic、df、p_value、cohens_d、ci_lower、ci_upper。
因为是聚合函数,它们天然支持 GROUP BY、窗口函数、DuckDB 的并行执行。你把 10 亿行按地区分组,每个组跑一个 ANOVA,查询计划自己就并行化了。
OLS 回归——支持稳健标准误
SELECT * FROM lm('mtcars', y := 'mpg', x := ['wt', 'hp']);
出来就是一张系数表:estimate、std_error、t_statistic、p_value。要模型摘要,用 lm_summary——R²、调整 R²、F 检验、残差标准误。
lm_fit 更狠——它是一个聚合函数,支持 GROUP BY:
-- 按地区分组,每组拟合一个回归,用 HC3 稳健标准误 SELECT region, lm_fit(y, x, vcov := 'HC3') FROM panel_data GROUP BY region;
标准误选项:classical、HC0、HC1、HC2、HC3,还有 cluster-robust(CR0/CR1)。做面板数据的同学应该很熟悉这套东西。
Table 1——医学论文标配
SELECT * FROM table_one('patients', variables := ['age', 'sex', 'bmi'], by := ['arm']);
table_one 输出的是医学/公卫论文里标准的"Table 1"——变量按分组描述(n、mean±sd、median [IQR]、n (%)),附组间比较 p 值和效应量。数值变量用 ANOVA,分类变量用卡方。一个函数调用,省掉 R 里 tableone 包的那一堆代码。
还有 corr_matrix(Pearson/Spearman/Kendall 相关系数矩阵)和 meta(每列的数据画像——类型、缺失率、分布、众数)。
分布函数——R 风格的 d/p/q/r
SELECT pnorm(1.96); -- 0.975(标准正态 CDF) SELECT qt(0.975, 30); -- 2.042(t 分布分位数) SELECT rnorm(); -- 随机抽样(volatile, per-row)
覆盖了 15+ 族分布:正态、t、卡方、F、Gamma、Beta、指数、Weibull、对数正态、Poisson、负二项、超几何。还有 bootstrap(x, statistic, n_iters) 用于自助法重抽样。
VISUALIZE——语法即图表
VISUALIZE table_name FROM data DRAW point;
用的是 Posit 发布的 Grammar-of-Graphics SQL 方言,编译到 Vega-Lite v5。不是服务器端渲染——扩展生成一个 spec + 每层的 SQL,客户端(浏览器/Jupyter)跑 SQL、喂数据给 Vega。所以图表是交互式的。
● ● ●
SAS/SPSS/Stata 文件直接读写
这可能是 stats_duck 最被低估的功能。
做医疗、政府、社会科学数据的同学都知道,SAS(.sas7bdat)、SPSS(.sav/.zsav)、Stata(.dta)这三个格式有多烦。明明只是表格数据,但要用专用软件或 Python 的 pyreadstat 才能读。
stats_duck 直接把它们变成了 DuckDB 的表格式:
SELECT * FROM read_sas('clinical_trial.sas7bdat');
SELECT * FROM read_spss('survey.sav');
SELECT * FROM read_stata('panel.dta');
而且支持写入——你可以用 DuckDB 处理好数据,直接写回这些格式,扔给还在用 SPSS 的合作者:
COPY (SELECT * FROM cleaned_data) TO 'output.sav' (FORMAT spss);
读写都走 DuckDB 的虚拟文件系统(httpfs://、s3://),所以你可以直接从 S3 读一个 SAS 文件,算完 t 检验,写回 S3。全程 SQL。
● ● ●
拿什么跟它比
说实话,在 DuckDB 生态里没有直接竞品。但如果把视野放宽:
| stats_duck | R + dplyr | Python + pandas + scipy | |
|---|---|---|---|
| 假设检验 | ✅ SQL 内聚合 | ✅ | ✅ |
| 回归 + 稳健 SE | ✅ HC0-HC3, CR | ✅ | ✅(statsmodels) |
| SAS/SPSS/Stata 读写 | ✅ 原生 I/O | ✅(haven) | ✅(pyreadstat) |
| 大规模数据 | ✅ 列存 + 并行 | 需 data.table | 需 dask/polars |
| 学习成本 | 如果你会 SQL | 要学 R 语法 | 要学 Python |
stats_duck 的独特价值很直白:R 和 Python 都能做统计,但你的数据已经在 DuckDB 里了。不用搬数据,跑统计就是一条 SQL。
● ● ●
局限和注意事项
- 不是 R/Python 的替代品。 它覆盖了日常统计工作流,但如果你要做混合效应模型、贝叶斯推断、生存分析,还是得回到 R/Python。
- v0.7.0,还在快速迭代。 计划中还有 Spearman/Kendall 相关分析、完整回归诊断、多重检验校正。
- VISUALIZE 需要客户端支持。 生成的 Vega-Lite spec 要在浏览器或 Jupyter 里渲染,不是服务器端出图。
- Windows MSVC 目前不构建。 MinGW 和 WASM 都支持。如果你用 WASM 版 DuckDB(浏览器里跑的),stats_duck 也能在里面跑。
● ● ●
怎么装
INSTALL stats_duck FROM community; LOAD stats_duck;
然后上面提到的所有函数就都可以用了。不需要装 R、不需要配 Python 环境、不需要 pip install 任何东西。
项目地址:github.com/KoliStat/the-stats-duck
DuckDB 的扩展生态正在从"连接器"进化到"工具箱"——先是空间计算(spatial)、全文搜索(fts)、向量检索(vss),现在是统计计算。SQL 的边界被一步步推远了。