2009-06-03 2 views
8

Версия разработки Django имеет совокупные функции, такие как Avg, Count, Max, Min, StdDev, Sum и Variance (link text). Есть ли причина, по которой медиан отсутствует в списке?Отсутствует функция «медианная» в Django?

Реализация одного кажется, что это будет легко. Я что-то упускаю? Каковы общие функции, выполняемые за кулисами?

ответ

7

Ну, причина причина, вероятно, вам нужно отслеживать все числа, чтобы вычислить медианную. Avg, Count, Max, Min, StDev, Sum и Variance могут быть рассчитаны с постоянными требованиями к хранению. То есть, как только вы «запишите» номер, вам больше не понадобится.

FWIW, переменные, которые необходимо отслеживать: min, max, count, <n> = avg, <n^2> = avg квадрата значений.

2

Сильная возможность заключается в том, что медиана не является частью стандартного SQL.

Кроме того, для этого требуется сортировка, что делает ее довольно дорогостоящей для вычисления.

+0

Есть линейные, не сортировочные, алгоритмы: http://valis.cs.uiuc.edu/~sariel/research/CG/applets/linear_prog/median.html –

+0

Неправильный алгоритм, я имел в виду медиана медиан : http://en.wikipedia.org/wiki/Selection_algorithm#Linear_general_selection_algorithm_-_.22Median_of_Medians_algorithm.22 –

+0

@Todd Gardner: Первая ссылка - это «общий выбор на основе разделов», а O (nlogn) - не линейный. Сайт неправильный. Было бы неплохо удалить этот комментарий, но оставим комментарий медианных медин. –

2

Я понятия не имею, какой db-бэкэнд вы используете, но если ваш db поддерживает другой агрегат, или вы можете найти умный способ сделать это, вы можете легко получить доступ к нему с помощью Aggregate.

1

FWIW, вы можете расширить PostgreSQL 8.4 и выше, чтобы иметь среднюю функцию агрегата с these code snippets.

Другие фрагменты кода (которые работают для более старых версий PostgreSQL): shown here. Обязательно прочитайте комментарии к этому ресурсу.

15

Вот ваша недостающая функция. Передайте ему QuerySet и имя столбца, который требуется найти медиану для:

def median_value(queryset, term): 
    count = queryset.count() 
    return queryset.values_list(term, flat=True).order_by(term)[int(round(count/2))] 

Это было не так сложно, как некоторые из других ответов, кажется, указывают. Важно, чтобы сортировка db выполняла всю работу, поэтому, если у вас уже индексированный столбец, это супер дешевая операция.

(обновление 1/28/2016) Если вы хотите быть более строгими об определении медианы для четного числа элементов, то это будет в среднее вместе значения двух средних значений.

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) 
+0

В этой реализации есть небольшая неточность, когда число элементов равно. Цитата из https://en.wikipedia.org/wiki/Median: «Если есть четное число наблюдений, то нет никакого среднего среднего значения, тогда медиана обычно определяется как среднее из двух средних значений ». Я думаю, что после того, как будет получен список values_list, лучше всего использовать функцию «медиана» python (для такой функции см. Этот поток: http://stackoverflow.com/questions/24101524/finding-median-of-list -in-python) –

+0

@o_c Это верный момент, но я не думаю, что это хорошая идея использовать медианную функцию python для всего набора данных - это дорогостоящая операция, в которой мне действительно нужно сделать небольшое изменение если счет даже. Я посмотрю, смогу ли я что-то сбросить. –

Смежные вопросы