Django 中缺少“中位数”聚合函数?

问题描述 投票:0回答:7

Django 的开发版本具有 Avg、Count、Max、Min、StdDev、Sum 和 Variance 等聚合函数(链接文本)。中位数没有出现在列表中是否有原因?

实施一个似乎很容易。我错过了什么吗?聚合函数在幕后做了多少工作?

python django aggregate-functions
7个回答
27
投票

这是您缺少的功能。向其传递一个查询集和您想要查找中位数的列的名称:

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)

15
投票

因为中位数不是 SQL 聚合。例如,请参阅 PostgreSQL 聚合函数列表MySQL 聚合函数列表


7
投票

好吧,原因可能是您需要跟踪所有数字才能计算中位数。 Avg、Count、Max、Min、StDev、Sum 和 Variance 都可以在存储需求恒定的情况下进行计算。也就是说,一旦您“记录”了一个号码,您就再也不需要它了。

FWIW,您需要跟踪的变量是:最小值、最大值、计数、

<n>
= 平均值、
<n^2>
= 值平方的平均值。


2
投票

很有可能中位数不是标准 SQL 的一部分。

此外,它需要进行排序,这使得计算成本非常昂贵。


2
投票

我不知道你正在使用什么数据库后端,但是如果你的数据库支持另一个聚合,或者你可以找到一种聪明的方法来实现它,你可能可以通过Aggregate轻松访问它。


1
投票

FWIW,您可以使用 这些代码片段扩展 PostgreSQL 8.4 及更高版本以拥有中值聚合函数。

其他代码片段(适用于旧版本的 PostgreSQL)显示在此处。请务必阅读此资源的评论。


0
投票

我现在已经实现了以下版本,因为上面的实现和舍入行为也得到了一些奇怪的结果。

使用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)
© www.soinside.com 2019 - 2024. All rights reserved.