2017-01-02 4 views
1

Предположим, у меня есть запрос на задание django объектов User. Каждый User имеет average_score. Как определить процентиль пользователя (верхние 10%, верхние 20% и т. Д.) На основе average_score?Вычисление процентиля из набора запросов django

Если бы я смог сортировать запрос, я бы теоретически мог бы принять индекс, деленный на общее количество (например, 5-е место из 100 баллов составляет 5%), но поскольку мы не можем сортировать запросы-то, что я могу сделать Вот?

ответ

1

Обновлен фрагмент, чтобы принять во внимание возможное деление на нулевую ошибку. Он получает количество объектов с average_score меньше, чем указано с помощью фильтра __lte queryset (Less than or equal to) и делится на общее количество объектов в базе данных.

Все это делается на конце базы данных, и (почти) никакие данные не передаются назад и вперед, поэтому он должен работать эффективно, даже с большим количеством пользовательских объектов в базе данных

queryset = User.objects.all() 
    total_count = queryset.count() 
    if total_count: 
     percentile = float(queryset.filter(average_score__lte=average_score).count())/total_count 
    else: 
     return 0.0 
+0

Будьте осторожны с делением на ноль! Ваш фрагмент не поймает эту ошибку. – Wilfried

+0

Правильно, я обновлю фрагмент. Этого не должно быть, хотя - average_score происходит от объекта User, поэтому в базе данных будет по крайней мере один объект. –

+1

http://stackoverflow.com/questions/11360858/what-is-the-eafp-principle-in-python Просто сообщение SO о принципах EAFP. Используется в ответе Санки. Больше пиронического. – Wilfried

1

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

import time 
from django import template 
from yourapp.models import Transaction 

register = template.Library() 
now_year = time.strftime("%Y") 

@register.simple_tag 
def graph_average_income_by_year(): 

    try: 
     transactions = Transaction.objects.filter(paid=True)\ 
              .filter(payment_date__year=now_year) 
     count_transactions = transactions.count() 
     incomes = [ p.total_transfer for p in transactions ] 
     return ("%.1f" % (float(sum(incomes))/count_transactions)) 
    except: 
     return 0.0 
Смежные вопросы