在django queryset中聚合并计算arrayfield的中值

时间:2016-04-25 20:55:15

标签: python django postgresql

我想知道这是否有可能以更有效的方式实现 我在PostGRESQL中有一个数据集,其结构如下:

Year, Sitename, Array (length = 4500)  

例如:

1982, DANC, array([2,3,4,5,6,7,...])  
1982, ANCH, array([5,6,4,3,5,7,...])  
1983, DANC, array([3,3,4,6,3,6,...])  
1983, ANCH, array([8,8,5,4,3,2,...])

我想要做的是按年累积数组(跨行)

E.G.,   
1982  1982  1982  
DANC  ANCH  TOT  
2     5     7  
3     6     9  
4     4     8  
5     3     8  
6     5     11  
7     7     14  
...   ...   ... 

我的Django模型看起来像这样:

class Abundance(models.Model):
    abundance_id = models.AutoField(primary_key=True)
    site = models.ForeignKey('Site')
    season = models.SmallIntegerField()        
    samples = ArrayField(models.DecimalField(blank=True, decimal_places=3, max_digits=30))

    def __unicode__(self):
        return self.site

我的Views.py中的以下代码有效:

import numpy as np
import bottleneck as bn
...


def testview(request):

    s = ["ACUN","BRDM"]
    quants = []
    medians = [] 
    for yr in range(1982,2015):                              
        X = Abundance.objects.values_list('samples').filter(site__site_id__in = s).filter(season = yr)
        h = np.matrix(np.array(X,dtype=float))    
        i = h.sum(axis=0)    
        m = bn.median(i)    
        up = np.percentile(i,95)
        down = np.percentile(i,5)
        qlist = [yr, round(down,3), round(up,3)]
        mlist = [yr, round(m,3)]
        quants.append(qlist)
        medians.append(mlist)

    return JsonResponse({'quants':quants, 'medians':medians})

但是,上面的代码非常慢 - 特别是在绘制许多网站时。我尝试过玩.aggregate(),但我找不到一个好的解决方案。

提前致谢

1 个答案:

答案 0 :(得分:0)

你可以使用那里的一些.aggregate()将负载推到Postgres,但我认为速度的一个更大的问题是Decimal字段。它具有最高的精度,但它也是Python移入和移出的更昂贵的类型之一。

那就是说,我不确定是否有快速的方法可以从DB调用中获取百分位数,但是你可以通过Django ORM轻松地将数据和中位数推送到数据库。对于其他人(百分位数等),你也可以将它们推倒,但是你将深入研究django(https://docs.djangoproject.com/en/1.9/ref/models/expressions/#creating-your-own-aggregate-functions)的自定义聚合,如果你要去那么远的话可能值得查看类似aldjemy(https://github.com/Deepwalker/aldjemy/)的内容并将整个查询转换为SQLAlchemy,以便您可以最大限度地控制它。