getEchartsData.py

from app.utils import getPublicData
# 从 app 应用的 utils 包中导入 getPublicData 模块
# getPublicData 是一个公共数据模块,提供了获取景点数据、用户数据等函数

import datetime
# 导入 Python 的 datetime 模块,用于处理日期和时间
# 这里主要用于将日期字符串转换为时间戳进行排序

travelInfoList = getPublicData.getAllTravelInfoMapData()
# 调用 getPublicData 模块中的 getAllTravelInfoMapData 函数
# 获取所有景点的完整数据,返回经过处理的景点对象列表
# 这个列表在全局范围内加载,供本模块的所有函数使用,避免重复查询数据库

# ============================================================================
# 城市和景点等级分析相关函数
# ============================================================================

def cityCharDataOne():
    # 定义获取城市分布数据(按省份统计)的函数
    # 用于生成柱状图或饼图,展示各省份的景点数量
    
    cityDic = {}
    # 初始化一个空字典,用于统计各省份的景点数量
    # 键是省份名称,值是该省份的景点数量
    
    for travel in travelInfoList:
        # 遍历所有景点对象
        
        if cityDic.get(travel.province, -1) == -1:
            # 检查当前景点所在的省份是否已经在字典中
            # dict.get(key, default) 方法:如果键存在返回对应的值,否则返回默认值 -1
            # 如果返回 -1,说明这个省份还没有被记录过
            
            cityDic[travel.province] = 1
            # 将这个省份加入字典,并设置数量为 1
        else:
            cityDic[travel.province] += 1
            # 如果省份已经存在,将其对应的数量加 1
    
    return list(cityDic.keys()), list(cityDic.values())
    # 返回两个列表:
    #   keys():省份名称列表,如 ['北京', '上海', '广东', ...]
    #   values():对应的景点数量列表,如 [15, 8, 23, ...]
    # 这种格式适合前端图表库(如 ECharts)直接使用

def cityCharDataTwo():
    # 定义获取城市分布数据(按景点等级统计)的函数
    # 用于展示不同等级景区(5A、4A等)的数量分布
    
    cityDic = {}
    # 初始化空字典,用于统计各等级景点的数量
    # 键是景点等级(如 '5A景区', '4A景区', '未评级'),值是该等级的数量
    
    for travel in travelInfoList:
        # 遍历所有景点对象
        
        if cityDic.get(travel.level, -1) == -1:
            # 检查当前景点的等级是否已经在字典中
            
            cityDic[travel.level] = 1
            # 如果不存在,加入字典并计数为 1
        else:
            cityDic[travel.level] += 1
            # 如果已存在,计数加 1
    
    resultData = []
    # 初始化结果列表
    
    for key, value in cityDic.items():
        # 遍历统计好的字典
        # key 是等级名称,value 是该等级的景点数量
        
        resultData.append({
            'name': key,
            'value': value
        })
        # 转换成 {name: '5A景区', value: 25} 的格式
        # 这种格式适合前端图表库的饼图、环形图等
    
    return resultData
    # 返回处理后的数据

# ============================================================================
# 评分情况分析相关函数
# ============================================================================

def getRateCharDataOne(travelList):
    # 定义获取评分分布数据(按星级统计)的函数
    # 参数 travelList 是景点对象列表(可能是筛选后的)
    # 统计各星级(如 45星、40星等)的景点数量
    
    startDic = {}
    # 初始化空字典,注意变量名拼写:startDic 应该是 starDic(星级字典)
    
    for travel in travelList:
        # 遍历传入的景点列表
        
        if startDic.get(travel.star, -1) == -1:
            # 检查当前景点的星级是否已经在字典中
            # travel.star 是星级评分,如 45 表示 4.5星
            
            startDic[travel.star] = 1
            # 如果不存在,加入字典并计数为 1
        else:
            startDic[travel.star] += 1
            # 如果已存在,计数加 1
    
    resultData = []
    # 初始化结果列表
    
    for key, value in startDic.items():
        # 遍历统计好的字典
        
        resultData.append({
            'name': key,
            'value': value
        })
        # 转换成 {name: '45', value: 12} 的格式
    
    return resultData
    # 返回星级分布数据

def getRateCharDataTwo(travelList):
    # 定义获取评分分布数据(按具体分数统计)的函数
    # 参数 travelList 是景点对象列表
    # 统计各分数(如 5.0、4.5、4.0等)的景点数量
    
    startDic = {}
    # 初始化空字典(同样有拼写问题,应该是 starDic)
    
    for travel in travelList:
        # 遍历所有景点
        
        if startDic.get(travel.score, -1) == -1:
            # 检查当前景点的分数是否已经在字典中
            # travel.score 是具体分数,如 '5.0'、'4.5' 等
            
            startDic[travel.score] = 1
            # 如果不存在,加入字典并计数为 1
        else:
            startDic[travel.score] += 1
            # 如果已存在,计数加 1
    
    resultData = []
    # 初始化结果列表
    
    for key, value in startDic.items():
        # 遍历统计好的字典
        
        resultData.append({
            'name': key,
            'value': value
        })
        # 转换成 {name: '5.0', value: 8} 的格式
    
    return resultData
    # 返回分数分布数据

# ============================================================================
# 价格销量分析相关函数
# ============================================================================

def getPriceCharDataOne(traveList):
    # 定义获取价格分布数据的函数
    # 函数注释:景点价格趋势分析
    # 将景点按价格区间分组统计
    
    xData = ['免费', '100元以内', '200元以内', '300元以内', '400元以内', '500元以内', '500元以外']
    # 定义价格区间的标签列表
    # 注意:第一个区间是'免费',但后面判断用的是 price <= 10,逻辑上应该是价格<=10元的视为免费
    
    yData = [0 for x in range(len(xData))]
    # 初始化一个与 xData 长度相同的零列表,用于存储各价格区间的景点数量
    # 列表推导式生成 [0, 0, 0, 0, 0, 0, 0]
    
    for travel in traveList:
        # 遍历所有景点
        
        price = float(travel.price)
        # 将景点的价格字段(字符串)转换为浮点数
        # 因为价格可能包含小数,所以使用 float()
        
        if price <= 10:
            # 如果价格小于等于 10 元,视为免费
            # 这里逻辑可能有问题:免费应该是 price == 0,但有些景点可能只收几元管理费
            yData[0] += 1
            # 第一个区间(免费)计数加 1
        
        elif price <= 100:
            # 如果价格在 10-100 元之间(包含100)
            yData[1] += 1
            # 第二个区间(100元以内)计数加 1
        
        elif price <= 200:
            # 如果价格在 100-200 元之间
            yData[2] += 1
        
        elif price <= 300:
            # 如果价格在 200-300 元之间
            yData[3] += 1
        
        elif price <= 400:
            # 如果价格在 300-400 元之间
            yData[4] += 1
        
        elif price <= 500:
            # 如果价格在 400-500 元之间
            yData[5] += 1
        
        elif price > 500:
            # 如果价格大于 500 元
            yData[6] += 1
    
    return xData, yData
    # 返回两个列表:价格区间标签和对应的景点数量

def getPriceCharDataTwo(traveList):
    # 定义获取销量分布数据的函数
    # 函数注释:景点销量分析
    # 将景点按销量区间分组统计
    
    xData = [str(x * 300) + '份以内' for x in range(1, 15)]
    # 生成销量区间标签
    # 列表推导式:x 从 1 到 14,生成标签如:
    # '300份以内', '600份以内', '900份以内', ... '4200份以内'
    
    yData = [0 for x in range(len(xData))]
    # 初始化一个与 xData 长度相同的零列表,用于存储各销量区间的景点数量
    
    for travel in traveList:
        # 遍历所有景点
        
        saleCount = float(travel.saleCount)
        # 将景点的销量字段(字符串)转换为浮点数
        
        for x in range(1, 15):
            # 循环遍历 1 到 14
            
            count = x * 300
            # 计算当前区间的上限,如 300、600、900...
            
            if saleCount <= count:
                # 如果当前景点的销量小于等于当前区间上限
                
                yData[x - 1] += 1
                # 对应区间计数加 1
                # 因为列表索引从 0 开始,而 x 从 1 开始,所以用 x-1
                
                break
                # 找到所属区间后跳出内层循环,避免重复计数
    
    return xData, yData
    # 返回销量区间标签和对应的景点数量

def getPriceCharDataThree(travelList):
    # 定义获取折扣分布数据的函数
    # 统计各种折扣类型的景点数量
    
    startDic = {}
    # 初始化空字典(变量名 startDic 应该是 discountDic)
    
    for travel in travelList:
        # 遍历所有景点
        
        if startDic.get(travel.discount, -1) == -1:
            # 检查当前景点的折扣类型是否已经在字典中
            # travel.discount 是折扣信息,如 '8折'、'学生票半价' 等
            
            startDic[travel.discount] = 1
            # 如果不存在,加入字典并计数为 1
        else:
            startDic[travel.discount] += 1
            # 如果已存在,计数加 1
    
    resultData = []
    # 初始化结果列表
    
    for key, value in startDic.items():
        # 遍历统计好的字典
        
        resultData.append({
            'name': key,
            'value': value
        })
        # 转换成 {name: '8折', value: 15} 的格式
    
    return resultData
    # 返回折扣分布数据

# ============================================================================
# 评论分析相关函数
# ============================================================================

def getCommentsCharDataOne():
    # 定义获取评论时间分布数据的函数
    # 统计每天有多少条评论,用于展示评论的时间趋势
    
    commentsList = getPublicData.getAllCommentsData()
    # 调用公共模块中的函数,获取所有景点的所有评论
    # 返回一个包含所有评论的列表,每个评论是一个字典
    
    xData = []
    # 初始化 xData 列表,用于存储评论日期
    
    def get_list(date):
        # 定义一个内部辅助函数,用于将日期字符串转换为时间戳
        # 参数 date 是日期字符串,格式如 '2024-03-19'
        
        return datetime.datetime.strptime(date, '%Y-%m-%d').timestamp()
        # datetime.strptime() 将字符串解析为 datetime 对象
        # 指定格式 '%Y-%m-%d' 表示年-月-日
        # timestamp() 将 datetime 对象转换为 Unix 时间戳(浮点数)
        # 时间戳可以方便地进行日期比较和排序
    
    for comment in commentsList:
        # 遍历所有评论
        
        xData.append(comment['date'])
        # 将每条评论的日期添加到 xData 列表
    
    xData = list(set(xData))
    # set() 将列表转换为集合,自动去重
    # 因为很多评论可能是同一天的,这里只保留唯一的日期
    
    xData = list(sorted(xData, key=lambda x: get_list(x), reverse=True))
    # sorted() 对 xData 进行排序
    # key=lambda x: get_list(x) 指定按日期的时间戳排序
    # reverse=True 表示降序排列,最新的日期在前
    
    yData = [0 for x in range(len(xData))]
    # 初始化与 xData 长度相同的零列表,用于存储每天的评论数量
    
    for comment in commentsList:
        # 再次遍历所有评论
        
        for index, date in enumerate(xData):
            # 遍历已排序的唯一日期列表
            # enumerate 同时获取索引(index)和日期值(date)
            
            if comment['date'] == date:
                # 如果当前评论的日期等于当前遍历到的日期
                
                yData[index] += 1
                # 对应日期的评论计数加 1
    
    return xData, yData
    # 返回两个列表:日期列表和对应的评论数量列表

def getCommentsCharDataTwo():
    # 定义获取评论评分分布数据的函数
    # 统计不同评分(1-5分)的评论数量
    
    commentsList = getPublicData.getAllCommentsData()
    # 获取所有评论列表
    
    startDic = {}
    # 初始化空字典(变量名应该是 scoreDic)
    
    for travel in commentsList:
        # 遍历所有评论
        # 注意变量名 travel 实际是 comment,容易引起误解
        
        if startDic.get(travel['score'], -1) == -1:
            # 检查当前评论的评分是否已经在字典中
            # travel['score'] 是这条评论的评分
            
            startDic[travel['score']] = 1
            # 如果不存在,加入字典并计数为 1
        else:
            startDic[travel['score']] += 1
            # 如果已存在,计数加 1
    
    resultData = []
    # 初始化结果列表
    
    for key, value in startDic.items():
        # 遍历统计好的字典
        
        resultData.append({
            'name': key,
            'value': value
        })
        # 转换成 {name: '5', value: 128} 的格式
    
    return resultData
    # 返回评论评分分布数据

def getCommentsCharDataThree():
    # 定义获取评论数量分布数据的函数
    # 统计景点按评论数量分组的分布情况
    
    travelList = getPublicData.getAllTravelInfoMapData()
    # 获取所有景点列表
    
    xData = [str(x * 1000) + '条以内' for x in range(1, 20)]
    # 生成评论数量区间标签
    # x 从 1 到 19,生成标签如:
    # '1000条以内', '2000条以内', '3000条以内', ... '19000条以内'
    
    yData = [0 for x in range(len(xData))]
    # 初始化与 xData 长度相同的零列表,用于存储各区间的景点数量
    
    for travel in travelList:
        # 遍历所有景点
        
        saleCount = int(travel.commentsLen)
        # 将景点的评论数字段(字符串)转换为整数
        
        for x in range(1, 20):
            # 循环遍历 1 到 19
            
            count = x * 1000
            # 计算当前区间的上限,如 1000、2000、3000...
            
            if saleCount <= count:
                # 如果当前景点的评论数小于等于当前区间上限
                
                yData[x - 1] += 1
                # 对应区间计数加 1
                
                break
                # 找到所属区间后跳出内层循环
    
    return xData, yData
    # 返回评论数量区间标签和对应的景点数量

函数功能总结

函数功能返回数据
cityCharDataOne统计各省份景点数量省份列表、对应数量列表
cityCharDataTwo统计各等级景点数量等级分布字典列表
getRateCharDataOne统计各星级景点数量星级分布字典列表
getRateCharDataTwo统计各分数景点数量分数分布字典列表
getPriceCharDataOne价格区间分布统计价格区间标签、对应数量
getPriceCharDataTwo销量区间分布统计销量区间标签、对应数量
getPriceCharDataThree折扣类型分布统计折扣分布字典列表
getCommentsCharDataOne评论时间趋势统计日期列表、对应评论数量
getCommentsCharDataTwo评论评分分布统计评分分布字典列表
getCommentsCharDataThree景点评论数量分布评论数区间标签、对应数量

这个模块是数据可视化的核心,负责将原始数据加工成各种图表所需的格式,为前端图表展示提供数据支持。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐