zoukankan      html  css  js  c++  java
  • MOOC课程信息D3.js动态可视化

    版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/83153693

    - 写在前面



      好久没更新博客了,主要还是最近太忙了。很久之前就看到B站上动态柱状图图表(用D3.js做的),详情见@Jannchie见齐的主页。感觉很不错,于是便自己也做一哈。正好前一阵子写了脚本对中国大学MOOC的课程信息进行了爬取,经过修改后弄成了定时爬虫。经过近一个月爬取,数据已经挺多的啦,可以开始类似动态展示了。

      如果需要查阅爬虫脚本的,可参见我的博客:

      中国大学MOOC课程信息爬取与数据存储

    - 环境配置



      运行环境:Python3.6、Spyder
      依赖的模块:pandas、mysql等

    - 开始工作


    1. 数据


      从9月20日至今,已有28张表格(以爬取日期命名),每张表格中都有一两千条课程数据,如下:

    2. 开源动态可视化项目


      下载开源项目

      Historical-ranking-data-visualization-based-on-d3.js

      解压打开后,可以看到示例的example文件




      步骤很简单,只需根据示例文件格式添加数据即可。对于比较复杂的设置,如添加顶部附加信息或自定义颜色等,打开config,js和visual.js进行相应修改。

      打开压缩包内的bargraph.html网页并添加待可视化的表格文件即可。

    3. 获取每天选课热度前10课程

    '''获取热度每天选课热度前15课程'''
    def get_top_hot(quire_condition):
        db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_infos',charset='utf8')    #连接数据库
        cur = db.cursor()
        sql = 'SHOW TABLES'
        cur.execute(sql)    #遍历所有表格
        tables= cur.fetchall()
        top_hot={}  #热度
        for table in tables:
            data=table[0][9:11]+'-'+table[0][12:14]  #日期标准化
            cur.execute("select course,id,stu_num from %s"% table+" where start_time like '%s'"% quire_condition+" ORDER BY stu_num desc limit 10")  
            result=cur.fetchall()
            top_hot[data]=result
        return top_hot
    
    '''热度top10课程写入CSV表格'''
    def save_csv(subject,top_hot):
        all_data=()   #所有数据初始化
        date=[]     #日期
        order=[]    #每日热度排名
        for data in top_hot:  
            _order=[i+1 for i in range(len(top_hot[data]))]  #每日排名编号
            order.extend(_order)
            all_data+=top_hot[data] #添加数据 
            date.extend([data for _ in top_hot[data]])  #日期
        dataframe = pd.DataFrame(list(all_data))  #数据字典化
        dataframe.columns = ['name','type','value']  #修改标签
        dataframe['type']=order  #将type列值改为每日热度的排名
        dataframe['date']=date   #添加日期列 
        path='C:\Users\Administrator\Desktop\Historical-ranking-data-visualization-based-on-d3.js-master\src\'
        '''将DataFrame存储为csv,index表示是否显示行名,default=True'''
        dataframe.to_csv(path+subject+'.csv',index=False,sep=',')  #写入csv
    

      需要说明的是因为课程进程不一致,为了相对公正一些,我这里将其分为三类:已结束的、正在进行的、即将开始的,分别获取每日热度top10。
    conditions={'已结束':'已结束%','即将开始':'%开课%','正在进行':'进行至%'}  #查询条件集
    condition='已结束'  #查询条件
    quire_condition=conditions[condition]  #SQL语句中的查询条件
    top_hot=get_top_hot(quire_condition)  #获取指定查询条件下所有课程热度前10
    save_csv(condition,top_hot)  #存入SCV表格
    

    4. 获取指定课程门类下每天选课热度前10课程

    '''获取指定门类课程名称和ID'''
    def get_kc_kind(subject): 
        subject_ids=[]
        db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_info2',charset='utf8')
        cur = db.cursor()
        cur.execute("select id from %s"% subject)    #获取表所有课程ID
        results=cur.fetchall()
        for result in results:
            subject_ids.append(result[0])
        return subject_ids
    
    '''获取指定门类课程的选课人数变化'''
    def get_hot_by_subject(subject_ids): 
        subject_ids=tuple(subject_ids)
        db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_infos',charset='utf8')
        cur = db.cursor()
        sql = 'SHOW TABLES'
        cur.execute(sql)   #遍历指定数据库所有表
        tables= cur.fetchall()
        top_hot={}  #热度
        for table in tables:  #特定日期
            data=table[0][9:11]+'-'+table[0][12:14]  #日期标准化
            '''查询条件:在指定门类下ID范围内;正在进行的课程;课程热度由高到低前10'''
            sql2 = "select course,id,stu_num from %s"% table+" where id in (%s)" % ','.join(['%d']*len(subject_ids)) % subject_ids 
                  +" and start_time like '进行至%' ORDER BY stu_num desc limit 10"
            cur.execute(sql2)
            result=cur.fetchall()
            top_hot[data]=result
        return top_hot
    


      这里值得说的是SQL查询语句where in下变量的表达,使用了format(花了不少功夫才得以解决)。

    subjects={'国家精品':'excellent_course','计算机':'computer','经济管理':'management','心理学':'psychology',
             '外语':'language','文学历史':'literary_history','艺术设计':'art','工学':'engineering',
             '理学':'science','生命科学':'biomedicine','哲学':'philosophy','法学':'law',
             '教育教学':'teaching_method'}
    _subjects=list(subjects.keys())  #课程门类中文名列表
    for subject in _subjects:
        subject_Eng=subjects[subject]  #课程门类英文名
        subject_ids=get_kc_kind(subject_Eng)  #获取该门类下所有ID
        subject_top_hot=get_hot_by_subject(subject_ids)  #该门类下每日课程热度前10
        save_csv(subject,subject_top_hot)  #写入CSV
    

    - 结果展示


    1. 正在进行的所有课程每日热度前10

    2. 即将开课的所有课程每日热度前10

    3. 已结束的所有课程每日热度前10

    4. 计算机门类下正在进行课程每日热度前10

    5. 国家精品门类下正在进行课程每日热度前10

    - 写在最后



      运行程序时发现挺快的,只有几秒钟,因此代码优化暂时不着急做。在绘制动态图表时,为了展示效果更好还需要学习下开源项目的代码,进行相应优化提升。另图表中有些Bug,比如有些值显示不出来,为NaN。

      最后还是非常感谢大佬的开源奉献!

  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/sc340/p/11870811.html
Copyright © 2011-2022 走看看