《JavaScript数据可视化编程》——1.5 用气泡图表示数量扩展x/y数据

1.5 用气泡图表示数量扩展x/y数据

像前面例子描述的传统离散型图表,只能展现x和y轴两个值之间的关系。有时两个值并不能恰当的展现出我们想要展现的数据。如果我们需要3个变量,我们可以使用一个离散型图表的框架来展现两个值,然后根据第三个值来改变图表中点的大小。那么使用气泡图就是最好的选择。

然而在使用气泡图时有一些需要注意的。像我们早先看到的饼图一样,人们非常不善于准确判断一个不是长方形形状的相对区域,所以气泡图不能让人们准确对比气泡的大小。但是,如果你只想展现一个大概的量而不是准确的量,那么使用气泡图是适合的。

在这次的例子中我们使用气泡图展现2005年卡特里娜飓风的路径。我们的x和y轴将会代表位置(纬度和经度),并且我们要确保我们的用户能准确地理解这些值。对于第3个值-气泡的大小-我们将使用风暴的持续风力,因为风速永远只是一个普通数值(并且风有时候大有时候小),所以使用持续风力是合适的。

就像本书1.1.1小节中一样,我们需要在我们的网站中包含Flotr2的类库,并且设置一个div元素来包含我们将要创建的图表。

1.5.1 第1步 定义数据
我们使用美国国家海洋和天气管理局(NOAA)的卡特里娜飓风的观察报告来做我们例子的数据。数据包括了飓风行进时的经纬度和每小时的风速。

var katrina = [
    { north: 23.2, west: 75.5, wind:  35 },
    { north: 24.0, west: 76.4, wind:  35 },
    { north: 25.2, west: 77.0, wind:  45 },
    // Data set continues...

对于气泡图,Flotr2需要每个数据点是一个数组而不是一个对象,所以我们要建立一个简单的函数将源数据转换成需要的格式。为了使函数更通用,我们可以传参指定一个过滤函数。当我们提取数据点时,我们可以反转经线符号从左到右显示由西向东。

function get_points(source_array, filter_function) {
1   var result = [];
     for (var i=0; i<source_array.length; i++) {
         if ( (typeof filter_function === "undefined")
           || (typeof filter_function !== "function")
           || filter_function(source_array[i]) ) {
             result.push([
                 source_array[i].west * -1,
                 source_array[i].north,
                 source_array[i].wind
            ]);
         }
     }
     return result;
 }

我们这段代码一开始在1的位置设置了一个返回值(result),是一个空数组。然后循环source_array,每次输入一个元素。如果filter_function参数是可用的,并且如果它是有效的函数,我们的代码会把源数组中当前元素作为参数在这个函数中进行调用。如果函数返回true,或者如果在get_points函数一开始的时候没有传filter_function函数参数,我们的代码会从源数组中的各个元素提取数据点然后push到result数组中。

正如你所看到的,filter_function参数是可选的。如果调用方省略它(或者不是一个有效的函数),那么在result中就是源的每个数据点。虽然我们现在并不马上使用过滤函数,但在这个例子后面的步骤中,我们就可以拿来就用了。

1.5.2 第2步 给图表创建背景图
因为我们图表中x和y轴的值表示的是坐标,用地图当作背景是再合适不过的了。为了避免涉及到版权的问题,我们使用stamen设计网站上的地图图片,使用OpenStreetMap网站的数据。这两者分别在Creative Commons CC 3.0和CC SA授权下可用。

当你使用地图时投影就成了棘手的问题,除了映射的地区更小以外,缺少有效的映射也是个问题,映射的地区都在图表中心的边缘。对于这个例子,我们将采取墨卡托投影来展示地图,在相对小的区域聚焦。假设我们已经将x、 y轴和经纬度进行了转换。

图1-21展示了将被我们用来覆盖飓风路径的地图。

1.5.3 第3步 绘制数据
一开始我们还是先从使用最少选项开始写代码,尽管这样我们需要迭代几次才能得到想要的图表。我们需要一个参数来指定气泡的半径。对于像这个例子中的静态图表,最简单的方法就是用几个值尝试找出最合适的尺寸。在我们的例子中使用了0.3这个值。除了前面的选项以外, draw方法还需要一个包含图表的HTML元素和数据本身。

Flotr.draw(
    document.getElementById("chart"),
    [{
        data: get_points(katrina),
        bubbles: {show:true, baseRadius: 0.3}
    }]
);

正如你所看到的,我们使用了前面写的转换函数来从源数据中提取需要的数据。这个函数的返回值直接被传递到draw方法的第二个参数中。

目前,我们还不用操心背景图片的问题。我们只需要把调整过的数据添加到图表中就可以了。图1-22中就是目前为止显示的效果,尽管还需要改进,但我们已经迈出了第1步。

1.5.4 第4步 添加背景
现在我们来看一下Flotr2是如何在背景图上绘制数据的。同时我们还想要做一些别的事情。首先我们添加一个背景图,移除掉网格线。其次,不显示轴线的标注;经纬线对于普通用户来说没有什么意义,地图对于用户来说也不是必需的。最后,也是最重要的,我们需要调整缩放图表来匹配地图图片。

Flotr.draw(
     document.getElementById("chart"),
     [{
       data: get_points(katrina),
       bubbles: {show:true, baseRadius: 0.3}
     }],
     {
1        grid: {
             backgroundImage: "img/gulf.png",
             horizontalLines: false,
             verticalLines: false
         },
2        yaxis: {showLabels: false, min: 23.607, max: 33.657},
3         xaxis: {showLabels: false, min: -94.298, max: -77.586}
     }
 );

我们在1的位置添加了一个grid的选项来告诉Flotr2不展示横纵网格线,并且指派一个用背景图片代替。我们想要图片展示的纬度值从23.607°N到33.657°N,经度值从77.568°W到94.298°W。所以在2和3的位置我们将这些值提供给xaxis和yaxis选项来当作的范围值,并且将两个轴的标注设置为不显示。需要注意的是因为我们涉及到的经度是西经,所以需要使用负值。

在图1-23中看图表这些点效果还不错。我们不仅可以清楚的看到飓风的路径还能看到飓风的强弱变化。

1.5.5 第5步 给气泡上色
在这个例子中,我们通过选项来修改气泡的颜色,可以让用户不用过于耗费精力就能获取到更多的信息。让我们在每个观察点上加上能表明萨菲尔-辛普森飓风等级的数字。

这里我们可以利用我们前面做的数据格式化函数来过滤一下要展现的数字。因为萨菲尔-辛普森飓风等级是基于风速的,所以我们要基于风的属性来过滤。例如下面的代码展现了只将风速74英里/小时到95英里/小时的值提取出来作为1级飓风等级。我们传给get_points函数的是返回为true的风速。

cat1 = get_points(katrina, function(obs) {
    return (obs.wind >= 74) && (obs.wind < 95);
});

我们用下面的代码来将数据划分到多个集合中,让Flotr2来分配不同的颜色给每个集合。除了5级飓风以外,我们已经解析出了热带风暴和热带气压的强度。

Flotr.draw(
    document.getElementById("chart"),
    [
      {
          data: get_points(katrina, function(obs) {
                    return (obs.wind < 39);
                }),
          color: "#74add1",
          bubbles: {show:true, baseRadius: 0.3, lineWidth: 1}
       },{
       // Options continue...
       },{
         data: get_points(katrina, function(obs) {
                   return (obs.wind >= 157);
               }),
         color: "#d73027",
         label: "Category 5",
         bubbles: {show:true, baseRadius: 0.3, lineWidth: 1}
       }
     ],{
       grid: {
           backgroundImage: "img/gulf.png",
           horizontalLines: false,
           verticalLines: false
       },
       yaxis: {showLabels: false, min: 23.607, max: 33.657},
       xaxis: {showLabels: false, min: -94.298, max: -77.586},
       legend: {position: "sw"}
     }
);

如你在图1-24中看到的,我们在左下角已经给飓风等级添加了标注和图例。

1.5.6 第6步 调整图例的样式
默认情况下,Flotr2会让所有元素看起来都尽可能的大。在图1-24中的图例就是一个好例子:它看起来很局促且不够吸引人。幸运的是,修改这个很简单:我们简单添加一些CSS的padding样式就可以了,我们也可以设置图例的背景颜色来和Flotr2的背景形成反差来突出。

.flotr-legend {
   padding: 5px;
   background-color: #ececec;
}
为了防止Flotr2给图例创建背景色,我们将透明度设置为0。

Flotr.draw(
    document.getElementById("chart")
        // Additional options...
        legend: {position: "sw", backgroundOpacity: 0,},
        // Additional options...

经过最后的调整,图1-25就是我们最终完成的样子。我们不想使用Flotr2的选项来指定标题,因为Flotr2将标题等也算在图表内容区内,所以当字数较多时,会将图表空间压缩收窄(并且我们也不能预知用户浏览器的字体大小)。这会导致纬度的变形。所以简单的用HTML标签来盛放标题就可以了。

气泡图相比二维的离散图表增加了其他维度。事实上,和我们的例子一样,它也可以进一步添加两个维度。在例子中使用气泡尺寸来代表风速,颜色表明飓风的分类。这两个值都需要关注。人们既不善于对比两个维度的区域,也不能轻松的对比相对的形状和颜色。气泡图从来都不应该用来表达一个临界数据或精确的数量。在例子中气泡图表现的很好,既不用准确的表示风速,也不用精确的指定飓风的位置。几乎没有人能区分出100/小时和110米/小时的差别,但他们能知道达拉斯和奥尔良的区别。

1.5.7 第7步 Flotr2“bugs”的应急预案
请参考本书1.1.9小节中关于创建基本柱状图表中是如何解决Flotr2类库的一些“bug”的。

时间: 2024-07-29 13:10:36

《JavaScript数据可视化编程》——1.5 用气泡图表示数量扩展x/y数据的相关文章

《JavaScript数据可视化编程》——1.4 用离散图表绘制x/y值

1.4 用离散图表绘制x/y值 柱状图对于单一数据维度的可视化展现通常是非常有效的就像我们之前创建的展现胜利场次的柱状图.但如果我们想要探索两种不同类型数据之间的关系离散型图表会更有效.假设我们想要展示一个城市健康体检的花费一个维度和平均寿命另一个维度之间的关系.让我们通过一个例子一步步的看看用数据是如何创建离散型图表的. 就像在本书1.1节介绍的一样我们需要在我们的网页中加载Flotr2类库并设置一个div元素来放置我们将构建的图表. 1.4.1 第1步 定义数据 在这个例子中我们将使用经济合

《JavaScript数据可视化编程》——导读

前言 JavaScript数据可视化编程 在我们的日常生活中,数据的重要性与日俱增.尤其对于一些庞大的组织机构(诸如Facebook和Google这种体量的公司)来说,数据几乎是一切决策的核心.在地缘政治领域,正在前所未有地收集数据,以致爆出诸如美国国家安全局监控丑闻这样的事件,这从另一个侧面反映了我们正在经历一个宏观数据时代.但是,从微观角度来说,数据作为一个个独立的个体,本身却并不显得那么重要.有调查称,99.5%的数据其实是被忽视和浪费的. 数据可视化是解决数据被浪费的重要工具.有效的可视

《JavaScript数据可视化编程》—— 第1章 图像数据1.1 创建基础的柱状图

第1章 图像数据 JavaScript数据可视化编程在很多人的印象中,数据可视化图形是一些非常酷炫复杂.充满科幻设计感的图形.这种看法其实存在误区.实际上,建立一个有效的数据可视化模型并不需要特别深厚的设计功底和复杂的编程技巧,如果你一直牢记着数据可视化的目的是帮助人们更好地理解数据,那么你就会认同,在进行数据可视化的过程中最需要注意的,恰恰是"简单"二字.那些看似简单基础.随处可见的图表及其所传达的信息,往往最容易为人们所理解和消化. 因为用户已经熟悉了各式各样的常规图表,如柱状图.

《Python数据可视化编程实战》—— 1.2 安装matplotlib、Numpy和Scipy库

1.2 安装matplotlib.Numpy和Scipy库 Python数据可视化编程实战 本章介绍了matplotlib及其依赖的软件在Linux平台上的几种安装方法. 1.2.1 准备工作 这里假设你已经安装了Linux系统且安装好了Python(推荐使用Debian/Ubuntu或RedHat/SciLinux).在前面提到的Linux系统发行版中,Python通常是默认安装的.如果没有,使用标准的软件安装方式安装Python也是非常简便的.本书假设你安装的Python版本为2.7或以上.

《Python数据可视化编程实战》——5.2 创建3D柱状图

5.2 创建3D柱状图 Python数据可视化编程实战 虽然matplotlib主要专注于绘图,并且主要是二维的图形,但是它也有一些不同的扩展,能让我们在地理图上绘图,让我们把Excel和3D图表结合起来.在matplotlib的世界里,这些扩展叫做工具包(toolkits).工具包是一些关注在某个话题(如3D绘图)的特定函数的集合. 比较流行的工具包有Basemap.GTK 工具.Excel工具.Natgrid.AxesGrid和mplot3d. 本节将探索关于mplot3d的更多功能.mpl

《Python数据可视化编程实战》—— 1.6 安装图像处理工具:Python图像库(PIL)

1.6 安装图像处理工具:Python图像库(PIL) Python数据可视化编程实战Python图像库(PIL)为Python提供了图像处理能力.PIL支持的文件格式相当广泛,在图像处理领域提供了相当强大的功能. 快速数据访问.点运算(point operations).滤波(filtering).图像缩放.旋转.任意仿射转换(arbitrary affine transforms)是PIL中一些应用非常广泛的特性.例如,图像的统计数据即可通过histogram方法获得. PIL同样可以应用在

《Python数据可视化编程实战》—— 1.5 在Windows上安装matplotlib

1.5 在Windows上安装matplotlib Python数据可视化编程实战在本节中,我们将演示如何安装Python和matplotlib.假设系统中没有预先安装Python. 1.5.1 准备工作 在Windows上安装matplotlib有两种方式.较简单的方式是安装预打包的Python环境,如EPD.Anaconda和Python(x,y).这是本书推荐的安装方式,尤其对于初学者来说更是如此. 第二种方式,是使用预编译的二进制文件来安装matplotlib和依赖软件包.需要注意安装的

《Python数据可视化编程实战》—— 1.8 在代码中配置matplotlib参数

1.8 在代码中配置matplotlib参数 Python数据可视化编程实战matplotlib库提供了强大的绘图功能,是本书用的最多的Python库.在其配置文件即.rc文件中,已经为大部分属性设定了默认值.本节会介绍如何通过应用程序代码修改matplotlib的相关属性值. 1.8.1 准备工作 如前所述,matplotlib配置信息是从配置文件读取的.在配置文件中可以为matplotlib的几乎所有的属性指定永久有效的默认值. 1.8.2 操作步骤 在代码执行过程中,有两种方式更改运行参数

《Python数据可视化编程实战》—— 1.9 为项目设置matplotlib参数

1.9 为项目设置matplotlib参数 Python数据可视化编程实战本节介绍matplotlib使用的各种配置文件的位置,以及使用这些配置文件的意义.同时还将介绍配置文件中的具体配置项. 1.9.1 准备工作 如果不想在每次使用matplotlib时都在代码开始部分进行配置(像前一节我们做的那样),就需要为不同的项目设定不同的默认配置项.本节将介绍如何做到这一点.这种配置方式使得配置项与代码分离,从而使代码更加整洁.此外,你可以很容易在同事间甚至项目间分享配置模板. 1.9.2 配置方法