Django项目如何创建动态查询统计所有状态下的各类Case数量
实现方案
你现有pandas代码的问题有两个:一是分组字段没覆盖你需要统计的所有属性维度,二是分组后调用value_counts()属于冗余用法,多字段分组计数直接用聚合函数即可。
下面给两种可落地的实现,根据你的场景选就行:
方案1:Django ORM原生聚合(优先选,性能最好)
数据量较大的时候不要把全表数据拉到内存转DataFrame,直接让数据库完成分组聚合,内存占用和响应速度都比pandas方案好很多,支持动态传参调整统计维度:
from django.db.models import Count # 要统计的维度字段可以动态修改,比如你要的4个属性就全传进去 stat_dimensions = ['case_type', 'status', 'sub_case', 'stage'] # 分组统计,返回结果直接是各维度组合+对应条数 stat_result = Case.objects.values(*stat_dimensions)\ .annotate(case_count=Count('id'))\ .order_by(*stat_dimensions)
返回的QuerySet里每个元素是字典格式,对应你给的样例数据会返回如下结果:
{'case_type': 'Basketball', 'status': 2021, 'sub_case': 'finished', 'stage': 'loss', 'case_count': 1} {'case_type': 'Basketball', 'status': 2022, 'sub_case': 'pending', 'stage': 'none', 'case_count': 1} {'case_type': 'Volleyball', 'status': 2020, 'sub_case': 'finished', 'stage': 'win', 'case_count': 2}
如果要单独查某一个属性组合的总条数,直接加filter即可:
# 统计volleyball - 2020 - finished - win的总条数 target_count = Case.objects.filter( case_type='Volleyball', status=2020, sub_case='finished', stage='win' ).count()
方案2:pandas实现(适合后续要做额外数据处理的场景)
如果你后续还要基于数据集做其他pandas分析,可以用这个方案,注意不要拉取表中不需要的字段,减少内存开销:
import pandas as pd from .models import Case # 只拉需要的统计维度字段,不要用all().values()拉全量字段 df = pd.DataFrame( list(Case.objects.values('case_type', 'status', 'sub_case', 'stage')) ) # 分组统计,as_index=False避免把分组字段设为索引 combo_stat = df.groupby( by=['case_type', 'status', 'sub_case', 'stage'], as_index=False ).size().rename(columns={'size': 'total_count'})
得到的combo_stat是标准DataFrame,每一行对应一组属性组合,total_count列就是该组合的总条数。如果要查询指定组合的数量,直接做布尔索引筛选即可:
# 查basketball - 2021 - finished - loss的条数 target_count = combo_stat[ (combo_stat['case_type'] == 'Basketball') & (combo_stat['status'] == 2021) & (combo_stat['sub_case'] == 'finished') & (combo_stat['stage'] == 'loss') ]['total_count'].iloc[0]
注意:单表数据量超过10w条时不要用pandas方案,全量数据加载到内存会带来明显的性能开销,优先选数据库层面的ORM聚合方案。
内容的提问来源于stack exchange,提问作者edche
相关产品推荐
相关产品推荐

