使用 DuckDB 计算描述性统计量

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

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

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

×
大家好!在本文中,我们将一起探索如何使用 DuckDB 对 CSV 数据进行常见的描述性统计计算。
无需导入库、无需创建表格,直接使用 SQL 语句就能快速对数据集进行初步分析。
我们会一起学习如何:

  • 直接读取并查询 CSV 文件
  • 计算数据的平均值和中位数
  • 求出标准差与方差
  • 找出最小值、最大值以及数据范围
  • 计算百分位数
  • 理解这些统计指标背后的含义
通过这篇文章,你将掌握如何用简单高效的 SQL 语句,快速了解数据的集中趋势、颠簸情况,甚至发现潜在的异常值。
下面用一个国内奶茶店外卖订单的场景演示。
假设有一份 waimai_orders.csv,字段包括:
  1. order_id, order_time, shop_name, category, amount, delivery_fee, distance_km, delivery_min
复制代码
我们要回答几个问题:

  • 平均每单多少钱?中位数多少?
  • 配送费平均多少?
  • 配送间隔和配送时长颠簸大不大?
  • 最贵、最自制、最远、最慢分别是多少?
  • 大部门订单金额落在什么区间?
所有操作都依赖 DuckDB 来完成。
1. 情况配置与数据加载

先安装 DuckDB 和 pandas:
  1. pip install duckdb pandas
复制代码
然后在 Python 里直接查 CSV:
  1. import duckdb
  2. con = duckdb.connect()
  3. con.sql("""
  4. CREATE OR REPLACE VIEW orders AS
  5. SELECT * FROM read_csv_auto('/opt/share/waimai_orders.csv')
  6. """)
  7. con.sql("SELECT * FROM orders LIMIT 5").df()
复制代码
order_idorder_timeshop_namecategoryamountdelivery_feedistance_kmdelivery_min10012025-03-01 02:41:00茶百道(春熙路店)奶茶20.73.01.52110022025-03-01 03:09:00喜茶(太古里店)果茶9.95.02.93410032025-03-01 03:10:00古茗(天府三街店)果茶11.84.01.02310042025-03-01 03:17:00喜茶(太古里店)咖啡38.03.01.01810052025-03-01 03:26:00喜茶(太古里店)奶茶38.53.04.037这里 DuckDB 的优势是:read_csv_auto 自动推断字段类型,CSV 直接当表查。
不用建表,不用导数,不用起服务,对探索式分析来说很省事。
2. 计算均值与中位数

均值和中位数要一起看。均值容易被极端大单拉高,中位数更接近“典型订单”。
  1. con.sql("""
  2. SELECT
  3.   AVG(amount) AS avg_amount,
  4.   MEDIAN(amount) AS median_amount,
  5.   AVG(delivery_fee) AS avg_delivery_fee,
  6.   MEDIAN(delivery_fee) AS median_delivery_fee,
  7.   AVG(distance_km) AS avg_distance,
  8.   MEDIAN(distance_km) AS median_distance,
  9.   AVG(delivery_min) AS avg_delivery_min,
  10.   MEDIAN(delivery_min) AS median_delivery_min
  11. FROM orders
  12. """).df()
复制代码
指标数值平均金额 avg_amount45.9058中位金额 median_amount29.15平均金额(45.91 元)比中位数(29.15 元)高不少,阐明有少数大单把平均值拉高了。
3. 计算标准差与方差

标准差衡量数值偏离均值的水平。
标准差越大,数据越分散。方差也是离散度,但单位是平方,解读不如标准差直观。
  1. con.sql("""
  2. SELECT
  3.   STDDEV(amount) AS std_amount,
  4.   VARIANCE(amount) AS var_amount,
  5.   STDDEV(delivery_min) AS std_delivery_min,
  6.   VARIANCE(delivery_min) AS var_delivery_min,
  7.   STDDEV(distance_km) AS std_distance,
  8.   VARIANCE(distance_km) AS var_distance
  9. FROM orders
  10. """).df()
复制代码
指标数值订单金额标准差 std_amount50.17订单金额方差 var_amount2517.48配送时长标准差 std_delivery_min10.49配送时长方差 var_delivery_min110.10配送间隔标准差 std_distance1.50配送间隔方差 var_distance2.26订单金额标准差约为 50.17,阐明订单金额差异非常大——有的单十几块,有的单大概上百块,分布很分散。
配送时长的标准差约为 10.49 分钟,意味着配送耗时颠簸明显:以平均配送时长(约 20 ~ 30 分钟)为中心,大部门订单送达时间会落在 均值 ±10 分钟左右 的范围内,也就是既有 20 多分钟就能送到的单,也大概出现 40 ~ 50 分钟甚至更久的订单。
配送时长的这种颠簸值得重点关注。
4. 计算最小值、最大值与范围

最小值、最大值看边界。范围就是最大值减最小值,快速了解数据跨度。
  1. con.sql("""
  2. SELECT
  3.   MIN(amount) AS min_amount,
  4.   MAX(amount) AS max_amount,
  5.   MAX(amount) - MIN(amount) AS range_amount,
  6.   MIN(delivery_min) AS min_delivery_min,
  7.   MAX(delivery_min) AS max_delivery_min,
  8.   MAX(delivery_min) - MIN(delivery_min) AS range_delivery_min,
  9.   MIN(distance_km) AS min_distance,
  10.   MAX(distance_km) AS max_distance,
  11.   MAX(distance_km) - MIN(distance_km) AS range_distance
  12. FROM orders
  13. """).df()
复制代码
指标数值最小金额 min_amount9.9 元最大金额 max_amount289.3 元金额极差 range_amount279.4 元最慢配送 max_delivery_min89 分钟最快配送 min_delivery_min18 分钟配送时长极差 range_delivery_min71 分钟最远间隔 max_distance12.3 公里最近间隔 min_distance0.5 公里间隔极差 range_distance11.8 公里最贵的订单约 289 元 ,大概是团餐;但金额极差到达 279 元,阐明客单价跨度非常大。
最远配送间隔约 12.3 公里 、最慢的订单用了 89 分钟 才送到,这种单固然占比大概不高,但会明显拉低整体配送体验。
如果这类"远间隔/超时长"订单的占比不低,就需要考虑是否要加收配送费,或者得当调整配送覆盖范围。
5. 计算百分位数

百分位数比均值更能看清分布。四分位数最常用:Q1 是 25% 分位,Q2 是中位数,Q3 是 75% 分位。
  1. con.sql("""
  2. SELECT
  3.   QUANTILE_CONT(amount, 0.25) AS q1_amount,
  4.   QUANTILE_CONT(amount, 0.50) AS median_amount,
  5.   QUANTILE_CONT(amount, 0.75) AS q3_amount,
  6.   QUANTILE_CONT(delivery_min, 0.25) AS q1_delivery_min,
  7.   QUANTILE_CONT(delivery_min, 0.50) AS median_delivery_min,
  8.   QUANTILE_CONT(delivery_min, 0.75) AS q3_delivery_min,
  9.   QUANTILE_CONT(distance_km, 0.25) AS q1_distance,
  10.   QUANTILE_CONT(distance_km, 0.50) AS median_distance,
  11.   QUANTILE_CONT(distance_km, 0.75) AS q3_distance
  12. FROM orders
  13. """).df()
复制代码
指标Q1中位数Q3金额19.77529.1544.675配送时长22.028.036.0配送间隔1.42.23.3这阐明:

  • 一半订单金额在 约 20 到 45 元 之间(Q1≈19.8 元,Q3≈44.7 元);
  • 75% 的订单金额低于 约 45 元;
  • 75% 的订单配送时长在 36 分钟 以内;
  • 75% 的订单配送间隔在 3.3 公里 以内。
这些数字可以直接用来做决策:重点服务 3.3 公里以内(75% 的订单都在这范围内),超过这个间隔可以加配送费;满减门槛可以围绕 45 元 附近计划,而不是拍脑袋定。
6. 总结与建议

DuckDB 在这类场景里很顺手:

  • 直接查 CSV,不用建表、不用导库;
  • SQL 写起来清晰,多个统计指标一次查完;
  • 输出 .df() 就能继续用 pandas、matplotlib;
  • 数据大一点也不虚,列式引擎,聚合快;
  • 改条件快,加个 WHERE 就能只看某天、某品类、某门店。
描述性统计不是尽头,但它是理解数据的第一步。
先算清晰均值、中位数、标准差、范围和四分位数,再决定下一步怎么分析。
比如继续 GROUP BY category 看品类,或者 date_trunc('day', order_time) 看每天趋势。
DuckDB 改 SQL 很快,适合这种快速探索。

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

使用道具 举报

登录后关闭弹窗

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