Отсутствует агрегатная функция «медиана» в Django?

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

Реализовать его кажется несложным. Я что-то упускаю? Какую часть агрегатных функций выполняют «за кулисами»?


person sutee    schedule 03.06.2009    source источник


Ответы (6)


Потому что медиана не является агрегатом SQL. См., например, список агрегатных функций PostgreSQL и список агрегатных функций MySQL.

person jacobian    schedule 03.06.2009

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

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

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

(обновление от 28.01.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)
person Mark Chackerian    schedule 29.02.2012
comment
В этой реализации есть небольшая неточность, когда количество элементов четное. Цитата из en.wikipedia.org/wiki/Median : если имеется четное количество наблюдений , то единого среднего значения нет; тогда медиана обычно определяется как среднее значение двух средних значений. Я думаю, что после получения списка значений лучше всего использовать «медианную» функцию python (для такой функции см. этот поток: stackoverflow.com/questions/24101524/) - person o_c; 28.01.2016
comment
@o_c Это правильное замечание, но я не думаю, что это хорошая идея использовать медианную функцию Python для всего набора данных - это дорогостоящая операция, в которой все, что мне действительно нужно сделать, это внести небольшое изменение, если счет четный . Я посмотрю, смогу ли я собрать что-нибудь вместе. - person Mark Chackerian; 28.01.2016
comment
Я знаю, что эта тема немного устарела, но действительно ли ваш обновленный ответ точен? например если в наборе запросов три значения, return values[int(round(3/2))] будет преобразовано в values[2]. Имхо, правильным решением будет return values[int(count/2)], которое разрешится в values[1]. - person RaideR; 29.05.2019
comment
@RaideR Этот ответ изначально был написан для Python 2, который имеет другое поведение округления. См. stackoverflow.com/questions/ 21839140/ . Так что вполне логично, что теперь в Python 3 есть некоторые ошибки, связанные друг с другом, в зависимости от того, является ли число нечетным или четным. Познакомится поближе. - person Mark Chackerian; 29.05.2019

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

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

person dmo    schedule 03.06.2009

Большая вероятность, что медиана не является частью стандартного SQL.

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

person S.Lott    schedule 03.06.2009
comment
Существуют линейные алгоритмы без сортировки: valis. cs.uiuc.edu/~sariel/research/CG/applets/linear_prog/ - person Todd Gardner; 03.06.2009
comment
Неправильный алгоритм, я имел в виду медиану медиан: / - person Todd Gardner; 03.06.2009
comment
@Todd Gardner: первая ссылка - это общий выбор на основе разделов, и он O (nlogn) нелинейный. Сайт неправильный. Было бы неплохо удалить этот комментарий, но оставить комментарий о медианах медиан. - person S.Lott; 03.06.2009

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

person SingleNegationElimination    schedule 03.06.2009

FWIW, вы можете расширить PostgreSQL 8.4 и более поздние версии, чтобы иметь медианную агрегатную функцию с помощью этих фрагментов кода.

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

person Mike T    schedule 06.07.2011