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

简介:

本节书摘来自异步社区《JavaScript数据可视化编程》一书中的第1章第1.4节作者 【美】Stephen A.Thomas 译者 翟东方 , 张超 , 刘畅 责编 陈冀康更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.4 用离散图表绘制x/y值

柱状图对于单一数据维度的可视化展现通常是非常有效的就像我们之前创建的展现胜利场次的柱状图。但如果我们想要探索两种不同类型数据之间的关系离散型图表会更有效。假设我们想要展示一个城市健康体检的花费一个维度和平均寿命另一个维度之间的关系。让我们通过一个例子一步步的看看用数据是如何创建离散型图表的。

就像在本书1.1节介绍的一样我们需要在我们的网页中加载Flotr2类库并设置一个div元素来放置我们将构建的图表。

1.4.1 第1步 定义数据
在这个例子中我们将使用经济合作与发展组织简称经合组织(OECD在2012年的报告。这个报告包含了健康体检花费价格占全国生产总值的比例还有平均寿命尽管这个报告是2012年年底发布的但它也包含了2010年的数据。在下面你会看到一小段摘录的数据存放在了JavaScript数组里。

var health_data = [
    {  country: "Australia",   spending: 9.1,    life: 81.8  },
    {  country: "Austria",     spending: 11.0,   life: 80.7  },
    {  country: "Belgium",     spending: 10.5,   life: 80.3  },
    // Data set continues...

1.4.2 第2步 格式化数据
像之前的例子一样我们需要重构原始数据来匹配Flotr2对数据格式的需要。如下面这段JavaScript代码展现的。我们一开始先定义一个空数组然后循环源数据health_data将源数据health_data中我们图表中需要的元素提取出来push到data数组中。

var data = [];
for (var i = 0; i < health_data.length; i++) { 
    data.push([ 
        health_data[i].spending,
        health_data[i].life
    ]);
};

因为Flotr2不需要依赖jQuery我们在例子中就没有用jQuery封装的函数。但如果你有其他原因在页面中使用了jQuery你可以使用一些封装函数例如使用.map()函数可以简化重构数据的代码。在2.1.7小节中有讲解jQuery的.map()函数的详细例子。

1.4.3 第3步 绘制数据
现在我们需要调用Flotr对象的draw()方法来创建我们的图表。我们首先尝试使用默认选项来创建。

Flotr.draw( 
    document.getElementById("chart"),
    [{ data: data, points: {show:true} }] 
);

如你所见Flotr2至少需要两个参数。首先一个是我们HTML文档中放置我们图表的元素第二个是一个数组里面存着图表的数据。通常Flotr2可以在同一个图表中绘制多个数据集的内容所以数组可能会有多个对象。因为在我们的例子中只绘制一个数据集所以数组中只有一个对象。这个对象会识别data属性并且告诉Flotr2用点来替代线展示用points属性替换lines属性。

图1-15展示了我们的结果注意看有一些点压在了图表的边缘。

screenshot

1.4.4 第4步 调整图表的轴
前面做的图表还不错但是Flotr2会自动计算每个轴的范围且默认的算法结果通常间距都很小。 Flotr2有一个autoscale的选项如果你设置了类库会尝试找到合适的范围自动关联x、 y轴。不幸的是在我以往的经验中Flotr2提供的默认选项对范围的选取很少有显著的改善所以大多数情况我们最好不去明确设置它们。下面会展示我们对图表怎么做。

Flotr.draw(
    document.getElementById("chart"),
    [{
        data: data, 
        points: {show:true}
    }],
    { 
        xaxis: {min: 5, max: 20},
        yaxis: {min: 70, max: 85}
    }
 );
我```  
们在draw()方法中添加了第三个参数包含我们想要的选项在这个例子中是x和y轴属性。在每个例子中我们都可以明确的设置一个最小值一个最大值。通过给数据指定范围留出空间使得我们的图表在图1-16中更易读。图1-17看法更好一些。

![screenshot](https://yqfile.alicdn.com/6486ef346acf9137cfecf12c8a30604a032dcfd8.png)

**1.4.5 第5步 标注数据**
我们的图表目前看来很合理但它并没有明确用户想看到的东西。我们需要添加一些标注来识别数据。再多加一些选项就可以阐明图表了。

Flotr.draw(

document.getElementById("chart"), 
[{ 
    data: data, points: {show:true}
}],
{ 
    title: "Life Expectancy vs. Health-Care Spending",
    subtitle: "(by country, 2010 OECD data)",
    xaxis: {min: 5, max: 20, 1tickDecimals: 0, 
            title: "Spending as Percentage of GDP"}, 
    yaxis: {min: 70, max: 85, 2tickDecimals: 0, title: "Years"} 
}

);

图表中的所有标题和次级标题都可以用title和subtile选项表示当title属性在xaxis和yaxis选项中时是用来命名这些轴的。除了添加标注我们还要在1和2的位置修改tickDecimals属性告诉Flotr2对于x和y轴的值不需要小数点。图1-17看上去更好一些。

![screenshot](https://yqfile.alicdn.com/43400181f38e86993fc196d8c75d0213fdf8da63.png)

**1.4.6 第6步 阐明x轴**
尽管通过我们前面的修改图表已经有了明显的改进但仍有一些数据描述上的烦人问题。 x轴代表了百分比但标注却显示的是一个整数。这个差别可能会导致我们的用户一开始有一些困惑所以让我们开始修正这个问题。 Flotr2允许我们按照我们的想法来格式化轴的标注。在这个例子中我们仅仅希望给值添加一个百分号足够简单。

Flotr.draw(
  document.getElementById("chart"),
  [{
  data: data, points: {show:true}
  }],
  {
  title: "Life Expectancy vs. Health-Care Spending",
  subtitle: "(by country, 2010 OECD data)",
  xaxis: {min: 5, max: 20, tickDecimals: 0,
  title: "Spending as Percentage of GDP",
1 tickFormatter: function(val) {return val+"%"}},
  yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"}
  }
 );

上面代码的关键是xaxis项下的tickFormatter属性代码1处。这个属性指定了一个函数。当tickFormatter被指定Flotr2就不会自动绘制标注而是调用我们定义的函数。将标注中数字的值当参数传给函数。 Flotr2会从函数中获取返回的字符串然后显示到标注上。在这个例子中我们仅仅在值后面添加了一个百分号。

在图1-18中用了添加百分比值标注的水平轴后我们的图表数据显得清晰了。

![screenshot](https://yqfile.alicdn.com/210c78efe58992e8de2cc2c9b68ed05b3c7c121c.png)

**1.4.7 第7步 回答用户的问题**
现在我们的图表已经成功的把数据展现出来了我们可以开始从用户的角度来更细致地改进可视化。我们尤其想要抢先回答用户可能提出的问题并且试着在图表中直接给出答案。在图表中至少暴露了三个问题

1都展示了哪些国家

2地区之间有哪些不同

3在右边远离其他数据的那个点是什么

可以用给每个数据点添加鼠标的mouseover事件或者加提示工具的方法来回答这些问题。有两个原因使我们不会在这个例子中使用前面说的方法。首先也是最明显的可视化交互是第2章的主题这一章只考虑静态图表和图像。其次mouseover和提示工具在用户使用触摸设备例如智能手机或者平板电脑访问我们的网站时是没有效果的。如果我们要求用户只有使用鼠标才能完全理解我们可视化的内容我们可能忽略了很大一部分用户并且是快速正增长的用户数。

我们解决这个问题的方法是将数据分成多个集合并且用不同的颜色和标注表明。首先我们要把数据拆分到各个地区。

var pacific_data = [

{ country: "Australia",      spending: 9.1,  life: 81.8 },
{ country: "New Zealand",    spending: 10.1, life: 81.0 }, 

];
var europe_data = [

{ country: "Austria",        spending: 11.0, life: 80.7 },
{ country: "Belgium",        spending: 10.5, life: 80.3 }, 
{ country: "Czech Republic", spending: 7.5,  life: 77.7 }, 

// Data set continues...

var us_data = [

{ country: "United States",  spending: 17.6, life: 78.7 }

];
因为用户可能想知道图表中右侧远离其他数据单独的那个点表示的是哪个国家而不仅仅想知道它属于哪个大洲所以我们就将美国的数据从美洲的数据集合中提取出来了。对于其他国家用各大洲就足够识别了。正因如此我们需要重新构建这些数组变成Flotr2的格式。这段代码和第4步一样我们只是把数据集重复一次。

var pacific=[], europe=[], americas=[], mideast=[], asia=[], us=[];
for (i = 0; i < pacific_data.length; i++) {

pacific.push([ pacific_data[i].spending, pacific_data[i].life ]);

}
for (i = 0; i < europe_data.length; i++) {

 europe.push([ europe_data[i].spending, europe_data[i].life ]); 

}
// Code continues...

一旦我们完成了国家的划分我们就可以把它们传给Flotr2了。这里我们可以看到为什么Flotr2期望数据格式是数组了每一个分隔的数据集在数组中是一个对象。

Flotr.draw(

document.getElementById("chart"),
[
    { data: pacific,    points: {show:true} },
    { data: europe,    points: {show:true} }, 
    { data: americas,  points: {show:true} },
    { data: mideast,   points: {show:true} }, 
    { data: asia,      points: {show:true} },
    { data: us,        points: {show:true} } 
],{ 
    title: "Life Expectancy vs. Health-Care Spending", 
    subtitle: "(by country, 2010 OECD data)", 
    xaxis: {min: 5, max: 20, tickDecimals: 0, 
            title: "Spending as Percentage of GDP",
            tickFormatter: function(val) {return val+"%"}},
    yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"}
}

);

如图1-19所示Flotr2用不同颜色表明不同的区域每个区域里是每个国家的数据。

![screenshot](https://yqfile.alicdn.com/356d8bfc8b40a382f08fc46b3902216f19722db0.png)


我们最后再提升一下表格的可读性我们添加一个图例来标明图表中颜色代表的地区。

Flotr.draw(
  document.getElementById("chart"),
  [
  { data: pacific, label: "Pacific", points: {show:true} },
  { data: europe, label: "Europe", points: {show:true} },
  { data: americas, label: "Americas", points: {show:true} },
  { data: mideast, label: "Middle East", points: {show:true} },
  { data: asia, label: "Asia", points: {show:true} },
  { data: us, label: "United States", points: {show:true} }
  ],{
  title: "Life Expectancy vs. Health-Care Spending (2010 OECD data)",
1 xaxis: {min: 5, max: 25, tickDecimals: 0,
  title: "Spending as Percentage of GDP",
  tickFormatter: function(val) {return val+"%"}},
2 yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"},

    legend: {position: "ne"}

  }
 );

为了给图例腾出空间我们在代码1处增加了X轴的范围并在代码2处将图例定位在图表的右上角。

图1-20就是添加完后图表的最终效果。

![screenshot](https://yqfile.alicdn.com/d780742642aa72738db8cca30a7a6357cc7c5472.png)


**1.4.8 第8步 解决Flotr2的“bugs”**
相关文章
|
JavaScript 前端开发
js实现数据的双向绑定
js实现数据的双向绑定
572 156
|
Web App开发 数据采集 JavaScript
动态网页爬取:Python如何获取JS加载的数据?
动态网页爬取:Python如何获取JS加载的数据?
1854 58
|
JavaScript 算法 前端开发
采招网JS逆向:基于AES解密网络数据
采招网JS逆向:基于AES解密网络数据
466 0
|
数据采集 JavaScript 前端开发
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
用array.filter()来实现数据筛选、数据清洗和链式调用,相对于for循环更加清晰,语义化强,能显著提升代码的可读性和可维护性。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
数据采集 存储 JavaScript
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
本文介绍了如何使用Puppeteer和Node.js爬取大学招生数据,并通过代理IP提升爬取的稳定性和效率。Puppeteer作为一个强大的Node.js库,能够模拟真实浏览器访问,支持JavaScript渲染,适合复杂的爬取任务。文章详细讲解了安装Puppeteer、配置代理IP、实现爬虫代码的步骤,并提供了代码示例。此外,还给出了注意事项和优化建议,帮助读者高效地抓取和分析招生数据。
639 0
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
|
前端开发 JavaScript
JS-数据筛选
JS-数据筛选
212 7
|
JavaScript 数据安全/隐私保护
2024了,你会使用原生js批量获取表单数据吗
2024了,你会使用原生js批量获取表单数据吗
339 4
|
JavaScript 前端开发 安全
js逆向实战之烯牛数据请求参数加密和返回数据解密
【9月更文挑战第20天】在JavaScript逆向工程中,处理烯牛数据的请求参数加密和返回数据解密颇具挑战。本文详细分析了这一过程,包括网络请求监测、代码分析、加密算法推测及解密逻辑研究,并提供了实战步骤,如确定加密入口点、逆向分析算法及模拟加密解密过程。此外,还强调了法律合规性和安全性的重要性,帮助读者合法且安全地进行逆向工程。
582 11
|
JSON JavaScript 数据格式
js实现更新数据
js实现更新数据
246 1

热门文章

最新文章