查看原文
其他

教程 | 选情数据可视化,一张地图展示中期选举动态(上)

Max Mapbox 2019-06-01


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中国


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存