alitrack

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_duckR + dplyrPython + 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 的边界被一步步推远了。