我正在尝试计算 Django 查询中的加权百分比。
这是我的数据的示例:
id start_date agency_id area_id housetype_id no_of_changed price_change_percentage total
6716 2017-08-26 11 1 1 16 -0.09 35
6717 2017-08-26 11 1 3 44 -0.11 73
6718 2017-08-26 11 1 4 7 -0.1 12
6719 2017-08-26 11 1 5 0 0 4
6720 2017-08-26 11 1 6 0 0 1
6721 2017-08-26 21 1 1 0 0 1
6722 2017-08-26 34 1 1 0 0 1
6723 2017-08-26 35 1 1 0 0 1
6724 2017-08-26 38 1 1 0 0 1
这是我当前的代码:
from django.db.models import F, FloatField, ExpressionWrapper
from app.models import PriceChange
def weighted_percentage(area_id, date_range, agency_id, housetype):
data = PriceChange.objects.filter(area_id=area_id,
start_date__range=date_range,
agency_id=agency_id,
)
if housetype:
data = data.filter(housetype=housetype) \
.values('start_date') \
.annotate(price_change_total=ExpressionWrapper((F('price_change_percentage') * F('no_of_changed')) / F('total'), output_field=FloatField())) \
.order_by('start_date')
else:
# what to do?
pass
x = [x['start_date'] for x in data]
y = [y['price_change_total'] for y in data]
return x, y
我弄清楚了在定义房屋类型时如何进行计算,并且我只需要一行中的数据。当我需要计算具有相同 start_date 的多行时,我不知道该怎么做。我不想为每一行提供一个值,而是为每个 start_date 提供一个值。
作为示例(具有相同 start_date、area_id、agency_id 但不同 housetype_ids 的两行): no_of_changed 价格变化百分比总计 16 -0.09 35 44 -0.11 73
计算采用伪代码:
((no_of_changed[0] *price_changed_percentage[0]) + (no_of_changed[0] *price_changed_percentage[0]))/(total[0] + Total[1]) =price_change_total
((16 * -0.09) + (44 * -0.11)/(35 + 73) = -0.03148148
我使用的是 Django 1.11 和 Python 3.6。
最佳答案
您需要将表达式包装在 Sum 表达式中。
添加以下导入:
from django.db.models import Sum
然后添加以下查询
else:
data = data.values('start_date') \
.annotate(
price_change_total=ExpressionWrapper(
Sum(F('price_change_percentage') * F('no_of_changed')) / Sum(F('total')),
output_field=FloatField()
)
) \
.order_by('start_date')
这里发生的情况是,当您在 annotate()
调用中使用聚合表达式(例如 Sum
)时,它会被转换为 group_by
在数据库中查询。前面 values()
子句中列出的所有列都用于创建 group_by
查询。
参见this blog post以获得 SQL 查询结果的进一步解释和分割。
关于python - Django 加权百分比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46101673/