主题河流图

终于是好像比较高级的图了hhhh但其实早在2008年都有比较出色的运用了,

2008年2月,《纽约时报》发布了一个最典型、最著名的河流图的例子《电影的衰退和流动:过去20年的电影票房收入》,描述了从1986年1月到2008年2月期间,所有电影的上映时间以及期间的周票房变化。在这个河流图中,流形状的宽度代表了某部电影的周票房,流形状的起始是由电影的上映时间决定的。颜色由电影的总票房决定,票房就是电影的“附加定量”,颜色越深代表了电影最终票房越高。

echarts themeRiver 主题河流图 数据格式 js pyecharts河流图_可视化

那么应该怎么去看这个看上去花里胡哨的河流图呢?

河流图(Streamgraph),有时候也叫做 主题河流图(ThemeRiver,是堆积面积图的一种变形,通过“流动”的形状来展示不同类别的数据随时间的变化情况。但不同于堆积面积图,河流图并不是将数据描绘在一个固定的、笔直的轴上(堆积图的基准线就是x轴),而是将数据分散到一个变化的中心基准线上(该基准线不一定是笔直的)

echarts themeRiver 主题河流图 数据格式 js pyecharts河流图_pyechart_02

总结一下:应用场景就是当你需要探索几个不同的主题的热度(或其他统计量)随时间的演变趋势,并在同时期进行比较时,这个图就挺实用的。

你比如说,我想看看第二季度小米10、小米10青春版,红米k30pro、华为nova 7、荣耀30S、荣耀X10这六种手机在微博话题上的热度变化,我就可以用主题河流图来展示。

用的当然是pyecharts了,强大的可视化工具。

Code

def themeRiver():

    from pyecharts.charts import ThemeRiver


    # x_data = ["小米10_青春版", "小米10_pro", "红米k30pro", "华为nova 7", "荣耀X10", "荣耀30S"]
    x_data=["k30pro", 'mi10_young', 'mi10&pro']
    y_data = [
        ['2020/3/1', 11, 'k30pro'], ['2020/3/2', 16, 'k30pro'], ['2020/3/3', 19, 'k30pro'], ['2020/3/4', 10, 'k30pro'],['2020/3/5', 31, 'k30pro'], ['2020/3/6', 11, 'k30pro'], ['2020/3/7', 12, 'k30pro'], ['2020/3/8', 9, 'k30pro'],['2020/3/9', 7, 'k30pro'], ['2020/3/10', 15, 'k30pro'], ['2020/3/11', 10, 'k30pro'],['2020/3/12', 21, 'k30pro'], ['2020/3/13', 13, 'k30pro'], ['2020/3/14', 9, 'k30pro'],['2020/3/15', 20, 'k30pro'], ['2020/3/16', 69, 'k30pro'], ['2020/3/17', 155, 'k30pro'],['2020/3/18', 92, 'k30pro'], ['2020/3/19', 110, 'k30pro'], ['2020/3/20', 25, 'k30pro'],['2020/3/21', 59, 'k30pro'], ['2020/3/22', 55, 'k30pro'], ['2020/3/23', 72, 'k30pro'],['2020/3/24', 530, 'k30pro'], ['2020/3/25', 135, 'k30pro'], ['2020/3/26', 75, 'k30pro'],['2020/3/27', 93, 'k30pro'], ['2020/3/28', 59, 'k30pro'], ['2020/3/29', 50, 'k30pro'],
         ['2020/3/30', 92, 'k30pro'], ['2020/4/1', 27, 'k30pro'], ['2020/4/2', 26, 'k30pro'],
         ['2020/4/3', 22, 'k30pro'], ['2020/4/4', 13, 'k30pro'], ['2020/4/5', 27, 'k30pro'], ['2020/4/6', 31, 'k30pro'],
         ['2020/4/7', 45, 'k30pro'], ['2020/4/8', 27, 'k30pro'], ['2020/4/9', 29, 'k30pro'],
         ['2020/4/10', 19, 'k30pro'], ['2020/4/11', 20, 'k30pro'], ['2020/4/12', 18, 'k30pro'],
         ['2020/4/13', 23, 'k30pro'], ['2020/4/14', 23, 'k30pro'], ['2020/4/15', 52, 'k30pro'],
         ['2020/4/16', 44, 'k30pro'], ['2020/4/17', 29, 'k30pro'], 
         ......
        ['2020/3/1', 1, 'mi10_young'], ['2020/3/2', 2, 'mi10_young'], ['2020/3/3', 2, 'mi10_young'], ['2020/3/4', 0, 'mi10_young'], ['2020/3/5', 1, 'mi10_young'], ['2020/3/6', 2, 'mi10_young'], ['2020/3/7', 3, 'mi10_young'], ['2020/3/8', 0, 'mi10_young'], ['2020/4/25', 4, 'mi10_young'], ['2020/4/26', 910, 'mi10_young'], ['2020/4/27', 921, 'mi10_young'], ['2020/4/28', 479, 'mi10_young'], ['2020/4/29', 288, 'mi10_young'], ['2020/4/30', 228, 'mi10_young'], ['2020/5/1', 91, 'mi10_young'], ['2020/5/2', 141, 'mi10_young'], ['2020/5/3', 85, 'mi10_young'], ['2020/5/4', 70, 'mi10_young'], ['2020/5/5', 83, 'mi10_young'], ['2020/5/6', 9, 'mi10_young'], 
        ......
        ['2020/6/10', 33, 'mi10&pro'], ['2020/6/11', 55, 'mi10&pro'], ['2020/6/12', 27, 'mi10&pro'],

    ]

    tr= (
        ThemeRiver(init_opts=opts.InitOpts(width="1300px", height="700px"))
            .add(
            series_name=x_data,
            data=y_data,
            singleaxis_opts=opts.SingleAxisOpts(
                pos_top="50", pos_bottom="50", type_="time"
            ),
        )
            .set_global_opts(
            tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="line"),
            legend_opts=opts.LegendOpts(pos_left='50%')
        )

    )
    return tr

还在爬取补全的数据,所以代码里暂时就先是三个手机。从3.1到6.12的不完全数据。

其实这个图的整个代码结构是pyecharts一脉相承的风格,数据集的请求结构也相对而言不算复杂,只不过当你数据量一大起来,什么玩意儿都要难搞一些。

这里也再贴一下我整理数据结构的代码吧,就是从爬虫爬取到的标准时间得到['2020/03/01', 321, 'mi10_young']这个结构的过程:

'''
@file: themriver_pre.py
@time: 2020/7/3 15:36
@author:Seepen
'''


import pandas as pd
from datetime import datetime
import numpy as np

t = pd.read_csv('huawei_nova7.txt', encoding='utf-8')
pubtime=t.发布时间
# print(pubtime)
# l=[]

#pub_time = pd.to_datetime(pubtime, format="%Y-%m-%d %H:%M")
df_time = pd.DatetimeIndex(pubtime)

data=np.zeros((4,30), dtype='int')
print(data.shape)


for i in df_time:
    m=i.month
    d=i.day
    if(d==31):
        d=30
    data[m-3][d-1]+=1

l=[]
for m in range(3,7):
    for d in range(1,31):
        if(d==31):
            d=30
        l.append(["2020/"+str(m)+"/"+str(d), data[m-3][d-1], "huawei_nova7"])

print(l)

是个笨办法。。但本来就是实验代码嘛,又不看这些脏活。
最后print出来的就是函数需要的数据结构:

[['2020/4/18', 159, 'huawei_nova7'], ['2020/4/19', 157, 'huawei_nova7'], ['2020/4/20', 178, 'huawei_nova7'], ['2020/4/21', 197, 'huawei_nova7'],
...]

直接贴到view的函数里即可。

最终画出的效果图:

echarts themeRiver 主题河流图 数据格式 js pyecharts河流图_pyechart_03

打完收工。