HoloViews
的安装
1 2 3 4
| conda create -n test # 新建一个叫做"test"的环境 conda activate test # “唤醒”test 环境
|
1 2 3 4 5
| conda install -c pyviz holoviews bokeh # 安装 holoviews; # 跑个题:bokeh 是前些年用来画和弦图的包,近年来不再被维护,被分到了另一个叫做 bkcharts 的包中。不幸的是,这个包是付费的。holoviews 暂时的神! conda install matplotlib plotly ipykernel # 以防万一——使用 holoviews 画某些图,需要 matplotlib 和 plotly 作为后端,因此需要安装。
|
使用 HoloViews
绘制和弦图
- 首先,请确认您正确安装了
HoloViews
。
- 如是,上述环境中应该已经正确安装了
ipykernel
—— 这样,您就可以在 vscode
中使用 jupyter notebook
实时查看 HoloViews
画出的成图。
- 在文件夹内新建
holochord.ipynb
,开始绘制和弦图。
导入所需的包
1 2 3 4 5 6 7 8 9
| import holoviews as hv from holoviews import opts, dim
import bokeh.sampledata bokeh.sampledata.download() from bokeh.sampledata.airport_routes import routes, airports
|
准备所需的数据
理解和弦图
- 和弦图描述事物之间的联系。
- 圆周上的一段弧表示一个事物;弧长越长,说明该事物和其他事物之间建立的联系数量越多。
- 圆内的每一条细线表示一个联系,我们看到的色带实际上是细线密集排布后形成的。
理解和弦图背后的数据
- 事物之间的联系可以类比为一个向量。
- 它有起点、有终点,有联系的“强度”(也可以理解为数量)。
- 为了绘制一幅和弦图,我们需要提供一份包括待研究事物、及这些事物之间**联系(links)**的数据:
- 横向上看,每一条联系由
source
, target
, value
组成,对应联系的“源”“流”“值”;
- 纵向上看,存在若干条联系;
- 因此,为了描述这些联系(即画出圆周内的部分),我们需要准备的数据,仅仅是一个 n 行 3 列的表;此外,为了画出圆周上的弧,我们还需要提供一份事物的名单。
理解之后,开始准备我们的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| route_counts = routes.groupby( ['SourceID', 'DestinationID'] ).Stops.count().reset_index()
nodes = hv.Dataset(airports, 'AirportID', 'City')
chord = hv.Chord((route_counts, nodes), ['SourceID', 'DestinationID'], ['Stops'])
|
问答时间
Q: 这里用的是包自带的数据集,如果我想给自己的数据做可视化,那么我应该如何准备数据呢?
A: Excel
yyds!将上面提到的两份表在 Excel
中准备好,使用 python
必学的数据处理包 pandas
中的一行命令,将 Excel
中的数据读入就可以了~
Q: 在 Excel
里准备这样两张表似乎挺麻烦的,因为常见的表不一定会以“起点-终点-联系数量”的形式来组织,那么如何给这些数据做前处理,让数据乖乖以 n 行 3 列的形式组织起来呢?
A: 这个只要简单学一下 pandas
就可以了,很简单的,真的。
绘图
- 绘图需要做的,就是选择你关心的部分,命令
HoloViews
帮你绘图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| busiest = list(routes.groupby('SourceID') .count() .sort_values('Stops') .iloc[-20:] .index .values)
busiest_airports = chord.select(AirportID=busiest, selection_mode='nodes')
busiest_airports.opts( opts.Chord( cmap='Category20', edge_color=dim('SourceID').str(), height=800, labels='City', node_color=dim('AirportID').str(), width=800 ) )
|