教程 | 选情数据可视化,一张地图展示中期选举动态(上)
2018年11月6日,美国中期选举即将开始。在一定程度上,这次选举对未来的中美关系和国际政治形势等都有着很重要的影响。
美国的选区为数众多,有什么办法可以一目了然地展示选举的投票状况呢?答案当然是数据可视化+地图啦!
在这篇教程中,Max 将带领大家制作一张选情地图,感受数据可视化的巨大作用。
本期教程分为上下两篇,在上篇中,我们将重点介绍表达式(Expression)这一灵活且功能强大的可视化工具,借助具体的例子,我们将探索不同类型的表达式和数据可视化方法。
我们将会用到种瓦片地图:QGIS,数据来自于美国官方,即展示美国选区的划分和分布,以及来自 Townhall.com 的2016年美国总统大选数据。形态上前者是多边形,后者是数据点。
我们用Excel表格展示以下类型的数据:
votes_dem 和 votes_gop 分别是美国两党获得的投票数。
total_votes 是总共获得的票数。
per_dem 和per_gop 是两党每位参选人所获的投票比例。
diff 是两位参选人的票数差距。
per_point_diff 是边际投票数,即以两位参选人的票数差距diff 除以总票数total_votes所得。
现在我们有了相应的数据,划重点时间来了!一起来了解下表达式(Expression)的用法。
表达式的构成与展示
表达式(Expression)以JSON数组构成,基本的数据格式为:[type_of_expression,argument_1, argument_2, ...]。其中,type_of_expression是表达式运算符,如同get,*或者case,类似的逻辑运算符还有许多。
表达式中的参数Argument可以是不同格式,如数字,字符串或者布尔值,甚至是另一个表达式。表达式可以作为数值用于任意布局属性、绘图属性或设置过滤条件。
表达式的具体应用
下面我们就进入将数据可视化的过程。
为了将选举的获胜一方从数据中挑选出来以便展示到地图上,我们需要用获得票数的相关表达式来得到赢得选举的数据点。以下为完成这一步的相关代码:
'paint': {
// fill-color to be determined by an expression
'fill-color': [
'case', // operator
['>', // operator
['to-number', ['get', 'votes_dem']], // get the democratic votes and convert to number since the original data type is a string
['to-number', ['get', 'votes_gop']] // get the gop votes and convert to number since the original data type is a string
],
'#1868d1', // blue
'#be2d1e' // fallback red
]
}
view raw
以上的代码逻辑为:检索votes_dem 和 votes_gop数据,如果votes_dem 大于votes_gop,将该地区的多边形以蓝色(#1868d1)渲染,反之则用红色( #be2d1e)渲染。在MapboxStudio的界面中,你可以通过点击瓦片区域来分别查看其对应的数据。
在以上的例子中,每一种数据均是字符串格式,这意味着对它们的计算需要使用to-number表达式来实现。
对边际投票率进行数据可视化
在这一部分中,我们将对每位参选者所获的边际投票率进行数据可视化。我们使用的是表达式中的use per_point_diff属性来实现。
'paint': {
'fill-color': [
'interpolate', // operator
['linear'], // linearly interpolate between each stop
['*', ['to-number', ['get', 'per_point_diff']], 100], // value we want to use
0, '#f6edf6', // stop
50, '#d77ddf', // stop
100, '#83048e' // stop
]
}
代码实现的是根据计算出的per_point_diff不同的数值(0-100)实现从#f6edf6到#d77ddf再到#83048e的颜色渲染。
到这一步,我们能够比较清晰的看到不同地区的投票情况了,但还是缺失了一个重要数据:在该地区究竟是红蓝两党哪一方的参选人获胜了?别急,我们即将实现这一步骤。
让颜色告诉你,获胜的究竟是哪一方?
之前,我们分别绘制了两张图——一张是显示各地获胜的参选人背景,另一张是各地的边际得票率。Magic Time!现在我们要将两张图合并起来。上代码:
'paint': {
'fill-color': [
'case', // operator
['>', // operator
['to-number', ['get', 'votes_dem']], // get the democratic votes and convert to number since the original data type is a string
['to-number', ['get', 'votes_gop']] // get the GOP votes and convert to number since the original data type is a string
],
[ // if the condition above is true, then use the following expression
'interpolate', // operator
['linear'], // linearly interpolate between each stop
['*', ['to-number', ['get', 'per_point_diff']], 100], // value we want to use
0, '#dce7f4', // stop: value, color
50, '#7697c2', // stop: value, color
100, '#1868d1' // stop: value, color
],
[ // if the condition above is false, then use the following expression
'interpolate',
['linear'],
['*', ['to-number', ['get', 'per_point_diff']], 100],
0, '#f5e4e4',
50, '#dd7e75',
100, '#be2d1e'
]
]
}
为获得更加的视觉效果,我们可以调整step表达式中的差值定义范围,来使颜色更加明显:
'paint': {
'fill-color': [
'case',
['>', ['to-number', ['get', 'votes_dem']], ['to-number', ['get', 'votes_gop']]],
[
'step',
['*', ['to-number', ['get', 'per_point_diff']], 100],
'#dce7f4',
10, '#bad2f0',
20, '#7697c2',
30, '#1868d1'
],
[
'step',
['*', ['to-number', ['get', 'per_point_diff']], 100],
'#f5e4e4',
10, '#f2cbcb',
20, '#dd7e75',
30,'#be2d1e'
]
]
}
view raw
哪个地区是一边倒的结果?
根据上一部分的地图,我们发现有些地区的获胜者获得了大多数的选票,取得了压倒性的胜利。这样的话,只使用颜色表达就差点意思。下面我们可以使用另一种方式,以圆圈大小来展示这一结论:
'paint': {
'circle-radius': [
'interpolate', // operator
['linear'], // type of interpolation
['to-number', ['get', 'diff']], // value
2, 2, // stop: smallest value, circle radius
1273485, 50 // stop: largest value, circle radius
],
'circle-color': [
'case',
['>', ['to-number', ['get', 'votes_dem']], ['to-number', ['get', 'votes_gop']]],
'rgba(24, 104, 209, 0.5)',
'rgba(190, 45, 30, 0.5)'
],
'circle-stroke-color': [
'case',
['>', ['to-number', ['get', 'votes_dem']], ['to-number', ['get', 'votes_gop']]],
'#124383',
'#691a12'
],
'circle-stroke-width': .5
}
代码中interpolate与之前是一样的,但我们根据得到的数据使用了circle-radius来将投票差值以圆形绘制,获得票数越多,圆圈越大。我们还可以使用filter来实现将投票差值在100000以内的地区过滤掉,让图像更加一目了然。
各位小伙伴们有没有get到表达式在数据可视化中的重要作用了呢,你还可以玩出更多有意思的花样哦!下一期我们会试着做一张实时更新数据的选举地图,大家记得先mark住~
👀相关阅读
25行代码加速可视化开发,Kinetica联合Mapbox发布开源库 Kickbox.js
刚刚!亚马逊 Alexa Auto 集成了 Mapbox 地图和导航服务
地图如何让旅行更感性?Mapbox 亚太区管理总监 Andy TDC演讲实录
您还可以在下面的渠道持续关注我们哦。
微博
@Mapbox地图数据平台,或者tag #mapbox#
知乎
@Mapbox中国