作者:木下瞳

在前段时间,小编推出了一篇 pyecharts 可视化仪表盘的制作教程:

《好看的 BI 大屏 Pyecharts 也可以做》

但存在几个问题,不能实时更新数据,制作的是静态的仪表盘,每次生成仪表盘都要调整代码,不能一运行就直接生成可视化仪表盘。

针对以上问题,这次小编带大家制作实时更新的可视化仪表盘。

可视化仪表盘一般以 web 形式展现是比较好的,源数据存储在类似 MySQL 的数据库中的,但为了简化问题,怕读者安装 MySQL 就耗费大量时间,及不懂 web,所以数据源采用 csv,没有使用 web。

来吧展示

↑ 实时更新的可视化仪表盘

数据生成

我们假设目标背景是某西餐厅想通过可视化仪表盘实时监控餐厅的状况,便于做出相应的人力物力等资源配置。

创建一个 data 文件夹专门用来保存数据,需要写一个实时更新插入新数据的脚本,用来达到数据实时更新的效果。

  • insert.py 为小编创建的脚本,此脚本先创建 3 张表:
  • food_sale.csv 菜品销量表,字段:菜品名,单价,销量(销量初始值为 0);
  • people.csv 人数状况表,字段:就餐人数,排队人数,座位数;
  • comment.csv 评论表,字段:评分,评论内容(评论内容每次从 comment.txt 中随机抽取内容作为评论,comment.txt 为小编随便复制的评论)

创建三张表并插入初始数据:

'''
创建 3 张表,并插入初始数据
'''
with open('data/food_sale.csv','w+',encoding='utf8',newline='') as f1,\
     open('data/people.csv','w+',encoding='utf8',newline='') as f2,\
     open('data/comment.csv','w+',encoding='utf8',newline='') as f3:
    w1 = csv.writer(f1)
    w2 = csv.writer(f2)
    w3= csv.writer(f3)

    # 插入头部
    w1.writerow(['food_name','price','sale'])
    w2.writerow(['eat_peo','queue_peo','seat'])
    w3.writerow(['score','comment'])

    # 为 food_sale.csv 插入初始数据
    w1.writerows([['菲力牛排', 75, 0],['果奶', 24, 0],['炸薯条', 17, 0],
                  ['套餐1', 88, 0], ['套餐2', 40, 0], ['套餐3', 57, 0],
                  ['意大利面', 35, 0], ['通心粉', 35, 0], ['西冷牛排', 67, 0],
                  ['罗宋汤', 25, 0], ['慕斯蛋糕', 15, 0], ['香煎三文鱼', 40, 0],
                  ['儿童餐', 35, 0], ['土豆泥', 15, 0], ['黄金虾', 45, 0],
                  ['咖喱牛肉饭', 35, 0], ['土豆饼', 15, 0], ['芝士蜗牛肉', 30, 0],
                  ['甜心薯块', 15, 0], ['南瓜粥', 15, 0], ['水果披萨', 20, 0],
                 ])



创建好以后,就开始插入数据,数据是一直插入的,小编设置的是间隔 1.5 秒插入一次,这里就用死循环就可以了,这样脚本就一直在运行插入新的数据。

先来插入菜品销量表的销量,销量初始为 0,numpy 随机生成和菜品数量一样长范围在 0-3 之间的数组,上一次的销量加上生成的数组成为新的销量,更新数据:

'''
每隔 1.5 秒更新一次数据
'''
while True:
    # food_sale.csv 菜品销量表更新菜品销量
    df1 = pd.read_csv('data/food_sale.csv',encoding='utf8')
    # 生成 [0,4) 之间长度为 21 的随机数组
    new_sale = np.random.randint(4, size=21)
    new_sale = pd.Series(new_sale).values
    # 更新销量,sale 字段
    df1['sale'] = new_sale + df1['sale']
    df1.to_csv('data/food_sale.csv',encoding='utf8',index=False)

再来插入人数状况表,总座位数设置为 50,就餐人数在 0-100 之间随机生成,大于 50,那就餐人数就为 50,排队人数就随机生成 10-30 之间的整数,如小于 50,排队人数就为 0,插入数据:

# people.csv 人数状况表插入
df2 = pd.read_csv('data/people.csv',encoding='utf8')
# 生成数据
eat_peo = random.randint(0,100)
if eat_peo > 50:
    eat_peo = 50
    queue_peo = random.randint(10,30)
else:
    queue_peo = 0
# 插入数据
s = pd.DataFrame({'eat_peo': [eat_peo], 'queue_peo': [queue_peo],'seat': [50]})
df2 = df2.append(s, ignore_index=True)
df2.to_csv('data/people.csv',encoding='utf8',index=False)

最后评论表,评分 1-5 分随机生成,评论从小编准备好的 txt 里面随机抽取,插入数据:

# comment.csv 评论表插入数据
df3 = pd.read_csv('data/comment.csv',encoding='utf8')
# 生成数据
score = random.randint(1,5)
f = open('data/comment.txt', 'r', encoding='utf8')
comments = f.readlines()
f.close()
comment = random.choice(comments)
# 插入数据
df3 = df3.append({'score' : score,'comment' : comment}, ignore_index=True)
df3.to_csv('data/comment.csv',index=False)
time.sleep(1.5)

好,运行此脚本就会在 data 文件夹生成数据,且脚本一直运行,数据一直更新。

可视化仪表盘

先来看看可视化仪表盘由哪些图构成,实现的代码获取源代码查看,这些图表都设置了 id。

菜品销量排行条形图:



销售额完成情况仪表盘:



就餐人数占总座位数的比重的水球图:



评分占比玫瑰图:



评论词云:



人数座位分布:



这些生成代码全都封装成函数,创建 page 对象调用它们,生成的可视化全部在 page.html 中,布局排版,保存 json文件,不明白的看文章开头链接的文章。

打开 json 文件可以看到有 cid 字段,这就是每张图表的 id,我们在布局好后,选中一张图表,右键【检查】,可以查看它的 id,此 id 在 json 中对应的地方找到,重新设置 id,假如此时右键后看到的 id 为 123,那在json 中找到 uid 为 123 的值,修改 uid 为1,在代码中找到此图的代码,设置 chart_id 为 1,依次把所有图表的都修改:



c = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK,chart_id=1))
        .add_xaxis(x)
        .add_yaxis("销量", y)
        .reversal_axis()
        .set_series_opts(label_opts=opts.LabelOpts(positinotallow="right"))
        .set_global_opts(title_opts=opts.TitleOpts(title="菜品销量排行"))
)
return c

id 全部修改好后,调用就可以生成仪表盘了,page.html 为生成的初始可视化图表,chart_config.json 布局文件,my_charts.html 最终可视化仪表盘。

最后需要实现实时刷新的功能,在最终可视化仪表盘中的 html 文件中添加一行刷新功能 html 代码即可,最后死循环读取,生成,刷新:

if __name__ == "__main__":
    while True:
        try:
            # 读取数据
            df1 = pd.read_csv('data/food_sale.csv', encoding='utf8',engine="python")
            df2 = pd.read_csv('data/people.csv', encoding='utf8',engine="python")
            df3 = pd.read_csv('data/comment.csv', encoding='utf8',engine="python")
        except Exception as e:
            continue
        # 生成可视化仪表盘
        page_draggable_layout()

        # 插入定时刷新的代码
        with open('my_charts.html','a+') as f1:
            refesh = '  '
            f1.write(refesh)

最后运行先运行 insert.py,再运行 visual.py,打开 my_charts.html 就可以看到每隔 3 秒自动刷新一次,就如“开门见山”所示。

源码获取

https://alltodata.cowtransfer.com/s/abc4cdfc65ea48

再次跟大家唠叨一下,目前凹凸数据采用的下载方式是奶牛快传。上面的链接只要复制到浏览器打开,点击左上方的下载即可(不限速下载)。



非常简单高效!