在 DuckDB 中执行假设检验

[复制链接]
发表于 4 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
你有没有想过,用 SQL 就能做假设检验?
今天我们就来聊聊,怎样用 DuckDB 快速完成数据分析中的两个经典使命:

  • 对分类变量做卡方检验
  • 对连续变量做相关性分析
整个流程非常丝滑:

  • 用 DuckDB 直接读取 CSV 或 Parquet 文件
  • 用熟悉的 SQL 做聚合计算
  • 把精简后的结果交给 Python 计算 p 值
  • 连续变量乃至可以直接用 DuckDB 内置的 corr() 函数搞定
看完你会发现自己又掌握了一个“快、准、狠”的数据分析利器!
下面用共享单车骑行记录来演示。
数据文件叫 bike_rides.csv,字段大概这些:

  • ride_id
  • user_type:月卡 / 单次
  • is_weekend:是 / 否
  • distance_km:骑行距离
  • duration_min:骑行时长
  • start_hour:开始小时
  • bike_type:普通车 / 电助力车
1. 环境准备
  1. # pip install duckdb pandas scipy
  2. import duckdb
  3. from scipy.stats import chi2_contingency
  4. con = duckdb.connect()
复制代码
DuckDB 的好处是,不消先建表,也不消把 CSV 导进数据库。直接查文件就行。
  1. con.execute("""
  2. SELECT *
  3. FROM read_csv_auto('bike_rides.csv')
  4. LIMIT 5
  5. """).df()
复制代码
ride_iduser_typeis_weekenddistance_kmduration_minstart_hourbike_type1月卡是2.5139普通车2月卡是3.21510电助力车3月卡是1.81014普通车4月卡是4.51916电助力车5月卡是5.1218普通车如果是 Parquet,就换成:
  1. read_parquet('bike_rides.parquet')
复制代码
这一步只是确认数据能读进来。真正做检验时,我们不会把全量数据拉到 Python,而是先用 DuckDB 做聚合。
2. 假设检验一:月卡用户和单次用户,周末骑行比例一样吗?

在我们探索数据的过程中,一个很自然的问题是:差别范例的用户在周末骑行的偏好上是否存在差别?
为了回答这个问题,我们可以借助分类变量的常用分析方法——卡方检验。
起首,我们设定一个简单的假设:

  • H₀(原假设):用户范例与周末是否骑行之间没有关联。
  • H₁(备择假设):用户范例与周末是否骑行之间存在某种关联。
这样的假设设定让我们可以更系统地探索数据背后的故事,而不是仅仅依赖直观感受。
接下来,我们就可以通过卡方检验来验证这些假设,看看数据是否支持我们拒绝原假设。
用 DuckDB 先聚合出列联表:
  1. df = con.execute("""
  2. SELECT
  3.     user_type,
  4.     SUM(CASE WHEN is_weekend = '是' THEN 1 ELSE 0 END) AS weekend,
  5.     SUM(CASE WHEN is_weekend = '否' THEN 1 ELSE 0 END) AS weekday
  6. FROM read_csv_auto('bike_rides.csv')
  7. GROUP BY user_type
  8. ORDER BY user_type
  9. """).df()
  10. print(df)
复制代码
user_typeweekendweekday单次4.016.0月卡14.06.0拿到列联表后,交给 scipy 做卡方检验:
  1. table = df[['weekend', 'weekday']].values
  2. chi2, p, dof, expected = chi2_contingency(table)
  3. print(f"卡方统计量: {chi2:.4f}")
  4. print(f"p 值: {p:.4f}")
复制代码
  1. 卡方统计量: 8.1818
  2. p 值: 0.0042
复制代码
结果分析:

  • p = 0.0042 < 0.05:拒绝 H₀,说明用户范例和周末骑行比例有关系。
  • 卡方统计量为 8.1818,在显著性水平 α = 0.05 下达到显著,有充足证据表明差别用户范例(单次 vs 月卡)在周末/工作日骑行比例上存在显著差别。
DuckDB 没有内置卡方检验,以是这里的分工是:DuckDB 负责把大表聚合成小列联表,scipy 负责算检验。
这样不会把全量骑行记录拉到 Python,内存压力小很多。
3. 假设检验二:骑行距离和骑行时长相关吗?

接下来,我们看看骑行的距离和骑行的时长之间到底有没有什么关系?
其实吧,这个问题听起来挺直觉的——骑得久,自然骑得远嘛。
但作为一个喜欢数据的人,咱不能光靠感觉说话,我们得拿出点真凭实据来。
以是我们可以提出两个假设:

  • 原假设(H₀):这两者之间啥关系都没有,也就是说,骑行距离和骑行时长完满是“各自为政”,互不干扰。
  • 备择假设(H₁):它们之间其实是有关系的,而且这个关系还挺显着的,不是偶合。
接下来,我们就可以用一些统计方法来检验一下,看看到底哪个假设更靠谱。
比如说,我们可以做一下相关性检验,算算它们之间的相关系数,看看是不是显著不为零。
这个可以直接用 DuckDB 的 corr():
  1. corr_df = con.execute("""
  2. SELECT
  3.     corr(distance_km, duration_min) AS corr
  4. FROM read_csv_auto('bike_rides.csv')
  5. WHERE distance_km IS NOT NULL
  6.   AND duration_min IS NOT NULL
  7. """).df()
  8. print(corr_df)
复制代码
计算出来的 corr=0.996897。
结果怎么读:

  • corr 接近 1:强正相关,距离越远,时长越长。
  • corr 接近 -1:强负相关。
  • corr 接近 0:基本没有线性相关。
DuckDB 直接算相关系数,不消把两列数据全部拉到 Python。数据量大时,这一点很省事。
如果你还想要 p 值,可以再用 scipy.stats.pearsonr,但通常先看 corr() 就能判断方向和强度。
4. 为什么这套流程适合用 DuckDB


  • 直接读 CSV / Parquet,不消先导入数据库。
  • SQL 聚合快,适合先做分组、计数、求和。
  • 卡方检验只需要列联表,DuckDB 聚合后数据很小,再给 scipy 很合适。
  • 相关性检验可以直接用 corr(),不消把全量数据搬到 Python。
  • 和 Python 衔接顺,con.execute(...).df() 直接拿 DataFrame。
5. 小结

这篇文章用共享单车场景演示了两个常见假设检验:

  • 分类变量比较:用户范例 vs 是否周末骑行,用卡方检验。
  • 连续变量关系:骑行距离 vs 骑行时长,用 Pearson 相关系数。
核心套路是:

  • 能用 SQL 聚合的,先让 DuckDB 做。
  • 需要统计检验的,再把小结果交给 Python。
  • 能直接用 DuckDB 内置函数的,比如 corr(),就别把数据拉出来。
换成其他字段,比如“差别品牌单车是否影响骑行时长”“早晚高峰与骑行距离”,流程基本一样。

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表