Django 的开发版本具有 Avg、Count、Max、Min、StdDev、Sum 和 Variance 等聚合函数(链接文本)。中位数没有出现在列表中是否有原因?
实施一个似乎很容易。我错过了什么吗?聚合函数在幕后做了多少工作?
这是您缺少的功能。向其传递一个查询集和您想要查找中位数的列的名称:
def median_value(queryset, term):
count = queryset.count()
return queryset.values_list(term, flat=True).order_by(term)[int(round(count/2))]
这并不像其他一些回复似乎表明的那么难。重要的是让数据库排序完成所有工作,因此如果您已经对列进行了索引,那么这是一个超级便宜的操作。
(更新2016年1月28日) 如果您想更严格地定义偶数个项目的中位数,这会将两个中间值的值一起平均。
def median_value(queryset, term):
count = queryset.count()
values = queryset.values_list(term, flat=True).order_by(term)
if count % 2 == 1:
return values[int(round(count/2))]
else:
return sum(values[count/2-1:count/2+1])/Decimal(2.0)
因为中位数不是 SQL 聚合。例如,请参阅 PostgreSQL 聚合函数列表 和 MySQL 聚合函数列表。
好吧,原因可能是您需要跟踪所有数字才能计算中位数。 Avg、Count、Max、Min、StDev、Sum 和 Variance 都可以在存储需求恒定的情况下进行计算。也就是说,一旦您“记录”了一个号码,您就再也不需要它了。
FWIW,您需要跟踪的变量是:最小值、最大值、计数、
<n>
= 平均值、<n^2>
= 值平方的平均值。
很有可能中位数不是标准 SQL 的一部分。
此外,它需要进行排序,这使得计算成本非常昂贵。
我不知道你正在使用什么数据库后端,但是如果你的数据库支持另一个聚合,或者你可以找到一种聪明的方法来实现它,你可能可以通过Aggregate轻松访问它。
我现在已经实现了以下版本,因为上面的实现和舍入行为也得到了一些奇怪的结果。
使用Python 3.11.4
def median_value(queryset, column_name):
count = queryset.count()
values = queryset.values_list(column_name, flat=True).order_by(column_name)
if count == 0:
return Decimal("0")
if count % 2 == 1:
return values[int(count/2)]
else:
return sum(values[int(count/2)-1:int(count/2)+1])/Decimal(2.0)