PostgreSQL中带amount列时如何计算selling_eur的中位数?
如何计算带数量权重的selling_eur中位数?
数据集
| 索引 | id | listing_id | category | amount | original_eur | selling_eur | user_id | rounds_id |
|---|---|---|---|---|---|---|---|---|
| 0 | 10088 | m1-1579cd77-6863-469d-8798-9e1bef199d2f | Category 2 | 2 | nan | 350.11 | eu-central-1:6fcfad76-ef06-4ea6-9e14-9fa4a5d62b8f | 31 |
| 1 | 10089 | m1-2adfde90-de27-4048-aa3e-bc7e76c03b0c | Prime Seats | 4 | nan | 962.81 | eu-central-1:6fcfad76-ef06-4ea6-9e14-9fa4a5d62b8f | 28 |
| 2 | 10090 | m3-024c20ad-e21d-4bb3-966e-44c69e760b15 | Category 1 | 4 | 200 | 750 | eu-central-1:33d3dbe4-6414-4949-ae21-f2bc8819ae4d | 29 |
| 3 | 10091 | m1-c612ad6c-d000-4bb5-8dc4-55e3b49d54cd | Category 2 | 4 | 150 | 450 | eu-central-1:fe695442-13a6-42e6-a015-046415bf369d | 28 |
| 4 | 10092 | m1-cd449fb2-6134-428b-946a-fc8a7bec30e7 | Category 1 | 4 | nan | 647 | eu-central-1:b926a781-4fc0-4f71-bd0f-69b50b0be68d | 28 |
问题描述
已知加权平均的计算方式为:sum(selling_eur * amount) / sum(amount),但不清楚如何计算带数量权重的中位数,同时询问是否可以通过生成包含重复价格的数组(比如第一行生成[350.11, 350.11])来计算中位数。
解决方案
1. 生成重复数组的思路完全可行
这种方法严格贴合中位数的定义:将所有单个数据点排序后,取中间值(或中间两个值的平均)。针对当前数据集:
- 展开所有数据点:
[350.11, 350.11, 962.81, 962.81, 962.81, 962.81, 750, 750, 750, 750, 450, 450, 450, 450, 647, 647, 647, 647] - 排序后:
[350.11, 350.11, 450, 450, 450, 450, 647, 647, 647, 647, 750, 750, 750, 750, 962.81, 962.81, 962.81, 962.81] - 总数据量为
2+4+4+4+4=18(偶数),中位数为第9和第10个值的平均:(647 + 647)/2 = 647
但这种方法在数据量较大时(比如amount值很大或行数极多)会占用过多内存,更高效的方式是用权重直接计算。
2. 高效的加权中位数计算方法(无需展开数组)
步骤如下:
- 按
selling_eur从小到大排序数据集 - 计算累计
amount,找到累计量达到总数量一半(或中间位置)的区间 - 根据累计量的位置确定中位数
针对当前数据集的计算过程:
- 总数量:
sum(amount) = 18,中间位置为第9和第10个数据点 - 排序后的数据集及累计amount:
selling_eur amount 累计amount 350.11 2 2 450 4 6 647 4 10 750 4 14 962.81 4 18 - 第9和第10个数据点都落在
selling_eur=647的区间内,因此中位数为647
3. Python代码实现(Pandas)
如果用Pandas处理,可以选择两种方式:
import pandas as pd # 构造数据集 data = { 'selling_eur': [350.11, 962.81, 750, 450, 647], 'amount': [2, 4, 4, 4, 4] } df = pd.DataFrame(data) # 方法1:展开数组计算(适合小数据集) expanded_values = df.loc[df.index.repeat(df['amount']), 'selling_eur'] median_expanded = expanded_values.median() print(f"展开数组计算的中位数:{median_expanded}") # 方法2:加权中位数计算(高效) df_sorted = df.sort_values('selling_eur') df_sorted['cum_amount'] = df_sorted['amount'].cumsum() total_count = df_sorted['cum_amount'].iloc[-1] median_position = total_count / 2 # 定位包含中位数位置的行 median_row = df_sorted[df_sorted['cum_amount'] >= median_position].iloc[0] median_weighted = median_row['selling_eur'] print(f"加权计算的中位数:{median_weighted}")
运行结果:
展开数组计算的中位数:647.0 加权计算的中位数:647
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

