马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
你有没有想过,用 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. 环境准备
- # pip install duckdb pandas scipy
- import duckdb
- from scipy.stats import chi2_contingency
- con = duckdb.connect()
复制代码 DuckDB 的好处是,不消先建表,也不消把 CSV 导进数据库。直接查文件就行。- con.execute("""
- SELECT *
- FROM read_csv_auto('bike_rides.csv')
- LIMIT 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,就换成:- read_parquet('bike_rides.parquet')
复制代码 这一步只是确认数据能读进来。真正做检验时,我们不会把全量数据拉到 Python,而是先用 DuckDB 做聚合。
2. 假设检验一:月卡用户和单次用户,周末骑行比例一样吗?
在我们探索数据的过程中,一个很自然的问题是:差别范例的用户在周末骑行的偏好上是否存在差别?
为了回答这个问题,我们可以借助分类变量的常用分析方法——卡方检验。
起首,我们设定一个简单的假设:
- H₀(原假设):用户范例与周末是否骑行之间没有关联。
- H₁(备择假设):用户范例与周末是否骑行之间存在某种关联。
这样的假设设定让我们可以更系统地探索数据背后的故事,而不是仅仅依赖直观感受。
接下来,我们就可以通过卡方检验来验证这些假设,看看数据是否支持我们拒绝原假设。
用 DuckDB 先聚合出列联表:- df = con.execute("""
- SELECT
- user_type,
- SUM(CASE WHEN is_weekend = '是' THEN 1 ELSE 0 END) AS weekend,
- SUM(CASE WHEN is_weekend = '否' THEN 1 ELSE 0 END) AS weekday
- FROM read_csv_auto('bike_rides.csv')
- GROUP BY user_type
- ORDER BY user_type
- """).df()
- print(df)
复制代码 user_typeweekendweekday单次4.016.0月卡14.06.0拿到列联表后,交给 scipy 做卡方检验:- table = df[['weekend', 'weekday']].values
- chi2, p, dof, expected = chi2_contingency(table)
- print(f"卡方统计量: {chi2:.4f}")
- print(f"p 值: {p:.4f}")
复制代码 结果分析:
- p = 0.0042 < 0.05:拒绝 H₀,说明用户范例和周末骑行比例有关系。
- 卡方统计量为 8.1818,在显著性水平 α = 0.05 下达到显著,有充足证据表明差别用户范例(单次 vs 月卡)在周末/工作日骑行比例上存在显著差别。
DuckDB 没有内置卡方检验,以是这里的分工是:DuckDB 负责把大表聚合成小列联表,scipy 负责算检验。
这样不会把全量骑行记录拉到 Python,内存压力小很多。
3. 假设检验二:骑行距离和骑行时长相关吗?
接下来,我们看看骑行的距离和骑行的时长之间到底有没有什么关系?
其实吧,这个问题听起来挺直觉的——骑得久,自然骑得远嘛。
但作为一个喜欢数据的人,咱不能光靠感觉说话,我们得拿出点真凭实据来。
以是我们可以提出两个假设:
- 原假设(H₀):这两者之间啥关系都没有,也就是说,骑行距离和骑行时长完满是“各自为政”,互不干扰。
- 备择假设(H₁):它们之间其实是有关系的,而且这个关系还挺显着的,不是偶合。
接下来,我们就可以用一些统计方法来检验一下,看看到底哪个假设更靠谱。
比如说,我们可以做一下相关性检验,算算它们之间的相关系数,看看是不是显著不为零。
这个可以直接用 DuckDB 的 corr():- corr_df = con.execute("""
- SELECT
- corr(distance_km, duration_min) AS corr
- FROM read_csv_auto('bike_rides.csv')
- WHERE distance_km IS NOT NULL
- AND duration_min IS NOT NULL
- """).df()
- 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企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |