本节书摘来自异步社区《JavaScript数据可视化编程》一书中的第1章第1.6节作者 【美】Stephen A.Thomas 译者 翟东方 , 张超 , 刘畅 责编 陈冀康更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.6 使用雷达图显示多维数据
如果你有多维的数据要展示那么选择雷达图是最有效的可视化方法。然而雷达图和其他图表不一样由于它们不常用比较陌生所以向用户解释的时候有一些难度。所以如果你想要使用雷达图要小心不要给用户增加认知负担。
当你的数据具备以下几个特性的时候那么雷达图是有效的表现形式
没有过多的数据点要显示。6个数据点是雷达图能容纳的最大限度了。
数据点有多个维度。如果你的数据只有2、 3个维度那么使用更传统的图表类型会更合适。雷达图更适合展现4个或更多的维度。
每个数据维度都是一个至少可以排名的量化标准换句话说就是从好到坏。雷达图不能仅仅表示某一个任意分类例如政党或国籍。
雷达图的一个典型用法是在一个球队中分析队员的竞技状态。在例子中我们使用NBA迈阿密热火队在2012年的先发阵容。只有5个数据点5个队员。有多个维度—得分、助攻、篮板和抢断等每一个维度都是一个自然数值。
表1-1显示了2011-2012赛季球员的场均数据和球队的数据总和包括替补队员的数据。

和1.1.1小节中一样我们需要在网页中添加Flotr2类库然后放置一个包含我们将要创建图表的div元素。
1.6.1 第1步 定义数据
我们用一个JavaScript表达式来表示球队的统计。在这个例子中我们用一个数组对象来对应每一个先发队员然后另外设置一个变量来表示整个球队。
var players = [
{ player: "Chris Bosh", points: 17.2, rebounds: 7.9, assists: 1.6,
steals: 0.8, blocks: 0.8 },
{ player: "Shane Battier", points: 5.4, rebounds: 2.6, assists: 1.2,
steals: 1.0, blocks: 0.5 },
{ player: "LeBron James", points: 28.0, rebounds: 8.4, assists: 6.1,
steals: 1.9, blocks: 0.8 },
{ player: "Dwyane Wade", points: 22.3, rebounds: 5.0, assists: 4.5,
steals: 1.7, blocks: 1.3 },
{ player: "Mario Chalmers", points: 10.2, rebounds: 2.9, assists: 3.6,
steals: 1.4, blocks: 0.2 }
];
var team = {
points: 98.2,
rebounds: 41.3,
assists: 19.3,
steals: 8.5,
blocks: 5.3
};
对于一个有效的雷达图我们需要按比例将所有的值标准化。在这个例子中我们将这些未加工的统计转换成球队的百分比。比如勒布朗·詹姆斯的得分是28.0分我们显示为29%28.0/98.2。
下面有两个函数我们使用这两个函数转换未加工的统计数据到图表的对象中。第一个函数返回单个队员的统计对象。这个函数通过在的players数组中寻找队员的姓名来进行简单的搜索。第2个函数逐个的从team对象中获取对应姓名队员的各个统计并标准化这些值。这个返回对象除了有一个等于队员姓名的label的属性外还有一个相应队员标准化统计数据的数组。
var get_player = function(name) {
for (var i=0; i<players.length; i++) {
if (players[i].player === name) return players[i];
}
}
var player_data = function(name) {
var obj = {}, i = 0;
obj.label = name;
obj.data = [];
for (var key in team) {
obj.data.push([i, 100*get_player(name)[key]/team[key]]);
i++;
};
return obj;
};
在这个统计中我们使用了一个从0到4的计数器。接下来我们来看如何将这些数值和有意义的文字匹配起来。
例如这个叫player_data("LeBron James")的函数返回下面这个对象。
{
label: "LeBron James",
data: [
[0,28.513238289205702],
[1,20.33898305084746],
[2,31.60621761658031],
[3,22.352941176470587],
[4,15.09433962264151]
]
}
因为Flotr2不依赖于jQuery所以在前面的代码中我们也没有使用jQuery封装好的简便函数。我们也没有充分利用JavaScript标准的函数包括像.each()方法因为IE9以前的浏览器不支持这些方法。如果因为其他原因你在页面中使用了jQuery或者你不需要支持老旧版本的IE浏览器那么你的代码会简单一些。
在代码的最后我们使用一个简单数组来匹配我们图表中的标注。这个顺序必须和player_data()的返回相对应。
var labels = [
[0, "Points"],
[1, "Rebounds"],
[2, "Assists"],
[3, "Steals"],
[4, "Blocks"]
];
1.6.2 第2步 创建图表
单独调用Flotr2的draw()方法来创建我们的图表我们需要指明将图表放到哪个HTML元素中还需要传递图表用到的数据。数据就通过我们前面展现的get_player()函数获取。
Flotr.draw(document.getElementById("chart"),
[
player_data("Chris Bosh"),
player_data("Shane Battier"),
player_data("LeBron James"),
player_data("Dwyane Wade"),
player_data("Mario Chalmers")
],{
1 title:
"2011/12 Miami Heat Starting Lineup - Contribution to Team Total",
radar: { show: true },
2 grid: { circular: true, },
xaxis: { ticks: labels, },
yaxis: { showLabels: false, min:0, max: 33, }
}
);
这段代码还包含了一些选项。在代码1处的title选项提供了一个图表的完整标题在代码2处的radar选项告诉Flotr2我们先要什么样的图表类型。使用雷达图我们需要明确指定一个圆形网格和矩形相反所以我们要在代码处设置grid选项。最后两个选项是x轴和y轴的详情。对于x轴我们使用labels变量数组来给每个统计点命名对于y轴我们完全放弃标注明确指出最大和最小值。
我们需要保证包含图表的HTML容器足够大能够显示下图表和图例因为FLotr2并不擅于计算合适的大小。对于像这样的静态图表反复试验是最简单的方法就像在图1-26中呈现给我们的图表一样。
2011/12赛季 迈阿密热火先发阵容对全队的贡献。

这个图表清楚地证明了勒布朗·詹姆斯对于球队的价值他在5个统计分类中 4项领先尽管这对于NBA的粉丝来说并不是什么新鲜事。
虽然雷达图只能在一些专门的情境下应用但当有适当数量的变量且每个都很容易量化时那么使用雷达图就很有效果。在图1-26中每个队员在图表中通过所有变量链接起来的区域大致对应他总的贡献。红色区域和其他颜色区域对比一下就显示出了詹姆斯对全队的总贡献非常突出。
1.6.3 第3步 Flotr2 “bugs”的应急预案
请参考本书1.1.9小节中关于创建基本柱状图表中是如何解决Flotr2类库的一些“bug”的。