如何基于计数字典计算Q1、中位数和Q3(无第三方库)
问题
我有如下形式的计数字典:
{1:2, 2:1, 3:1}
需要从中计算Q1、中位数和Q3。奇数样本量的情况计算起来很简单,但偶数样本量的情况我始终处理不好。要求不使用numpy等第三方库实现。
示例:
counts = { "4": 1, "1": 2, "5": 1 }
期望结果:
results = { "q1": 1, "median": 2.5, "q3": 4, }
我目前写了如下代码,但无法处理所有情况:
import math def get_ratings_stats(counts): """This function will return min, q1, median, q3 and max value from list of ratings.""" cumulative_sum = 0 cumulative_dict = {} for key, value in sorted(counts.items()): cumulative_sum += value cumulative_dict[key] = cumulative_sum q1_index = math.floor(cumulative_sum * 0.25) q3_index = math.ceil(cumulative_sum * 0.75) median_index = cumulative_sum * 0.5 q1, q3, median = None, None, None print('indexes: ', q1_index, median_index, q3_index) for key, sum in cumulative_dict.items(): if not q1 and sum >= q1_index: q1 = key if not q3 and sum >= q3_index: q3 = key if not median and sum >= median_index: median = key
解决方案
你的代码核心问题在于索引计算逻辑不准确,且未处理分位数刚好落在两个数值之间的情况(比如示例中的中位数需要取相邻值的平均值),同时字符串类型的键会干扰数值计算。以下是修正后的完整代码:
import math def get_ratings_stats(counts): """返回计数字典对应的最小值、Q1、中位数、Q3、最大值""" # 将键转换为数值并排序,确保处理顺序正确 sorted_items = sorted((int(k), v) for k, v in counts.items()) if not sorted_items: return {} # 空字典直接返回 total = sum(v for _, v in sorted_items) min_val = sorted_items[0][0] max_val = sorted_items[-1][0] # 构建累积计数列表,同时保存对应的数值 cumulative = [] current_sum = 0 for val, cnt in sorted_items: current_sum += cnt cumulative.append((val, current_sum)) # 定义获取分位数的辅助函数 def get_quantile(percentile): index = total * percentile # 遍历累积列表,找到对应的位置 for i, (val, cnt) in enumerate(cumulative): if cnt > index: # 索引为整数时,取当前值与前一个值的平均(存在前一个值的情况) if index.is_integer(): prev_val = cumulative[i-1][0] if i > 0 else val return (prev_val + val) / 2 else: return val elif cnt == index: # 累积计数等于索引时,取当前值与下一个值的平均(存在下一个值的情况) next_val = cumulative[i+1][0] if i < len(cumulative)-1 else val return (val + next_val) / 2 return max_val # 兜底返回最大值 # 计算各个分位数 q1 = get_quantile(0.25) median = get_quantile(0.5) q3 = get_quantile(0.75) return { "min": min_val, "q1": q1, "median": median, "q3": q3, "max": max_val } # 测试示例 counts = { "4": 1, "1": 2, "5": 1 } print(get_ratings_stats(counts)) # 输出: {'min': 1, 'q1': 1, 'median': 2.5, 'q3': 4, 'max': 5}
关键修正说明:
- 键类型转换:将字符串键转为整数,避免字符串排序错误(如"10"排在"2"前),同时支持数值计算。
- 累积计数结构:同时保存数值和对应的累积计数,便于快速定位分位数位置。
- 分位数逻辑优化:
- 当索引为整数时,说明分位数落在两个元素之间,取相邻数值的平均值。
- 当累积计数刚好等于索引时,取当前值与下一个值的平均值。
- 辅助函数复用:把分位数提取逻辑封装成函数,减少重复代码,提升可读性。
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

