在本系列的 第 1 部分 中,您已看到了如何使用 Apache Hadoop 处理大型数据。在示例中,您使用 Hadoop 处理 Apache web 服务器访问日志。使用 Hadoop 将这些日志转化为商业智能数据,该数据将会告诉您 web 站点的用户正在使用什么浏览器来访问您的站点。通过 Hadoop 您所作的有用的事情之一是将此数据格式化为 JSON,因为您知道您最终将要编写一个 web 应用程序,该应用程序将使用此数据并将其转化为图形报告。清单 1 显示了一些您将在本文中使用的示例数据。
清单 1. 示例浏览器用法数据
[
{"month" : "January 2010", "data":
{"IE8":5339680,"IPHONE":176397,"SAFARI":1161063,
"FF35":5334121,"OTHER":1697189,"IE6":2355910,"OPERA":293024,
"IE7":3448568,"FF3":1425939,"CHROME":1381381}},
{"month" : "February 2010", "data":
{"IE8":4420267,"IPHONE":122378,"SAFARI":937765,
"FF35":4904831,"OTHER":1249727,"IE6":1824138,"OPERA":261245,
"IE7":2548741,"FF3":848517,"CHROME":1122684}},
{"month" : "March 2010", "data" :
{"IE8":4832154,"IPHONE":124723,"SAFARI":1004835,
"FF35":5240639,"OTHER":1443493,"IE6":1782140,"OPERA":288338,
"IE7":2705560,"FF3":728227,"CHROME":1250771}},
{"month" : "April 2010", "data" :
{"IE8":6014148,"IPHONE":153317,"SAFARI":1184909,
"FF35":6355369,"IE6":2023596,"OTHER":1701331,"OPERA":336320,
"IE7":3083772,"FF3":794613,"CHROME":1895022}},
{"month" :"May 2010", "data" :
{"IE8":3985522,"IPHONE":107109,"SAFARI":826693,
"FF35":4443157,"OTHER":1350928,"IE6":1169420,"OPERA":230201,
"IE7":2032111,"FF3":471397,"CHROME":1358771}},
{"month" :"June 2010", "data" :
{"IE8":4944664,"IPHONE":143594,"SAFARI":597916,
"FF35":5396690,"OTHER":1740354,"IE6":1367462,"OPERA":264916,
"IE7":2318786,"FF3":511660,"CHROME":1594828}}
]
|
这是由本系列 第 1 部分 中所开发的 Hadoop 作业生成的数据。在此示例中,您将直接在 web 页面上包括该数据,但是将其包括在使用 Ajax 可以下载的单独文件中会更便利。正如您从 清单 1 中所看到的,您有六个月以 JSON 表示的浏览器统计信息。Web 应用程序可以很容易地使用该数据来创建报告。
有许多优秀的服务器端和客户端的框架和库,您可以使用它们根据此数据创建报告。要使您的报告具有高度交互性,您需要一个客户端解决方案,Dojo 工具包就非常适合。它具有二维和三维图表。对于本示例来说,我们将使用二维图表。清单 2 显示了如何创建基本图表。
清单 2. 用 Dojo 创建基本扇形图
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hadoop Reports</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojox.charting.Chart2D");
var pieChart = {};
var stats; // see Listing 1 for the stats
function init(){
pieChart = new dojox.charting.Chart2D("pie-chart");
pieChart.addPlot("default", {
type: "Pie",
radius: 300,
fontColor: "black",
labelOffset : "-50"
});
var lastMonth = stats[stats.length -1];
pieChart.addSeries("browsers", makePieSeries(lastMonth.data));
pieChart.render();
}
function makePieSeries(data){
var series = [];
var total = 0;
var key = "";
for (key in data){
total += data[key];
}
var label = "";
for (key in data){
label = key;
label += " : ";
label += data[key] * 100.0 / total;
label += "%";
series.push({y:data[key], text:label});
}
return series;
}
dojo.addOnLoad(init);
</script>
</head>
<body>
<div id="pie-chart" style="width: 800px; height: 750px;"></div>
</body>
</html>
|
在 清单 2 中要首先要查看的就是脚本块。请注意您使用 Dojo 的包管理系统(dojo.require)来下载 Dojo 的 2D 图表对象,即 dojox.charting.Chart2D。在 web 页面完成加载时,脚本块的最后一行使用 dojo.addOnLoad 函数来调用函数(在本例中是 init 函数)。在 init 函数中,您创建扇形图并在字符串 pie-chart 中将其传递给构造函数。这将告诉 Dojo 要寻找具有 ID pie-chart 的 HTML 元素并将其用作将要创建的图表的父元素。您可以在 清单 2 中的 HTML 结构中看到此元素。
返回到 init 函数,您要做的下一件事是在您已经创建的 chart 对象上调用 addPlot 方法。在这里您为图表指定选项,包括它将是哪种类型的图表。Dojo 支持许多类型的图表。在本例中,您指定 Pie 作为类型。许多选项对于图表类型来说是特定的。例如,在这里您为扇形图指定半径,但其并不适用于其他图表类型。
下一步,您要在 chart 对象上调用 addSeries 方法。您将在其中传递来自 清单 1 的数据。然而,您需要轻微地处理一下此数据以便使其完美地用于 Dojo 的扇形图,这就是 makePieSeries 函数所作的事情。它获取浏览器中的数据并返回简单对象数组。每一个对象都有两种属性:y 和 text。y 对象是值,而 text 是标签。在 makePieSeries 函数中的大多数代码都用于创建标签,此标签将显示浏览器的名称、有多少次点击以及总点击率。
返回到 init 函数,您要做的最后一件事是在图表上调用 render 函数。该函数实际上将促使 Dojo 在 web 页面上绘制图表。如前所述,一些绘图和系列选项根据图表的类型而不同。然而,addPlot/addSeries/render 模式是常见的。图 1 显示了该图表看起来将是什么样子。
图 1. 显示六月份浏览器统计信息的基本扇形图
图 1 中的图表是 Dojo 扇形图的基本框架。唯一不默认的就是对于图表中的那些扇区您具有自定义标签。虽然它可能不是您见过的最漂亮的图表,但是它图形化地显示了商业智能数据,同时它采用了非常少的代码来生成。正如您将要看到的,使此图表更美观一点相当容易。
Dojo 使创建基本扇形图变得很容易,就像您在 图 1 中看到的一样。这可能与您希望展示给此图表的决策制定者的显示版本的不完全相同。幸运的是,Dojo 使添加一些视觉效果变得很容易。清单 3 显示了一些针对 清单 2 中代码的更新,将生成色彩更丰富的且交互性更强的扇形图。
清单 3. 色彩丰富的扇形图代码
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.themes.Shrooms");
dojo.require("dojox.charting.action2d.MoveSlice");
dojo.require("dojox.charting.action2d.Tooltip");
function init(){
pieChart = new dojox.charting.Chart2D("pie-chart");
pieChart.addPlot("default", {
type: "Pie",
radius: 300,
fontColor: "black",
labelOffset : "-50"
});
var lastMonth = stats[stats.length -1];
pieChart.addSeries("browsers", makePieSeries(lastMonth.data));
var slice =
new dojox.charting.action2d.MoveSlice(pieChart,"default");
var tip = new dojox.charting.action2d.Tooltip(pieChart,"default",{
text : function(o) {
var run = o.run;
var item = run.data[o.index];
var label = item.text;
var split = label.split(" : ");
var browser = split[0];
var percentage = split[1];
var total = item.y;
return browser + " : " + total + " (" + percentage + ")";
}
});
pieChart.setTheme(dojox.charting.themes.Shrooms);
pieChart.render();
}
|
在 清单 3 中首先应注意的是已经添加了几个新的 dojo.require 调用。您将看到代码的后半部分将引用这些对象中的每个对象。第一个被使用的是 MoveSlice 对象。这是一个简单的动画,当鼠标悬停在扇形图的某个扇区上时该扇区将弹出。随后使用的是 Tooltip 对象。这允许显示工具提示,即当鼠标悬停在扇形图的某个扇区上时显示的一些额外文本。将要显示的默认文本只是扇形图特定扇区的标签。如果您想显示其他信息,就像在这里的操作一样,您要提供一个名为 text 的函数。此函数产生将显示为工具提示的文本。在本例中,它将会显示类似于 FF35 : 5334121 (27.48%) 的提示。最后,最后添加的是针对您图表的 setTheme 方法的调用,传递 Dojo 提供的诸多颜色主题中的一个。此操作提供一些鲜明的色彩。图 2 显示了扇形图的更加丰富多彩的版本。
图 2. 特别的色彩扇形图
现在更像了。正如您从 清单 3 中看到的,此主题被称为 Shrooms。您大概可以猜出原因。如果它对于您来说有点太亮的话,Dojo 提供了三十多个主题。您创建自己的主题也相当容易。此外,您不必使用主题。您可以为您扇形图的每一个扇区直接指定颜色。图 1 和 图 2 两个图中所显示的图表仅仅显示了来自 清单 1 的六月份数据。让我们来看看您如何处理其他月份的数据。
您可以很容易获取 清单 3 中的代码并使用它为来自 清单 1 的每一个月份的数据呈现图表。每一次,您将创建一个新的扇形图,这有一点低效。有一个更简洁和有效的方式来更改形成图表的数据。清单 4 显示了扇形图的修改版本,此版本允许用户选择将要显示的那个系列的数据。
清单 4. 带有数据切换控件的扇形图
function init(){
// same as in Listing 3
var chooser = dojo.byId("series-selector");
var i = 0;
var monthlyStats = null;
var opt = null;
for (i=0;i<stats.length;i++){
monthlyStats = stats[i];
opt = dojo.doc.createElement("option");
opt.value = i;
opt.appendChild(dojo.doc.createTextNode(monthlyStats.month));
chooser.appendChild(opt);
}
}
function aggregateResults(results){
var aggResults = {};
aggResults["IE"] = results.IE8 + results.IE7 + results.IE6;
aggResults["FF"] = results.FF35 + results.FF3;
aggResults["SAFARI"] = results.SAFARI + results.IPHONE;
aggResults["CHROME"] = results.CHROME;
aggResults["OPERA"] = results.OPERA;
aggResults["OTHER"] = results.OTHER;
return aggResults;
}
function selectSeries(){
var selected = dojo.byId("series-selector").value;
var aggBox = dojo.byId("aggBox").value;
var series = stats[selected].data;
if (aggBox){
series = aggregateResults(series);
}
pieChart.updateSeries("browsers", makePieSeries(series));
pieChart.render();
}
...
<div id="commandBar">
<label for="series-selector">Choose Data:</label>
<select name="series-selector" id="series-selector"
onchange="selectSeries()">
</select>
<label for="aggBox">Aggregate Data?</label>
<input type="checkbox" id="aggBox" name="aggBox"
onchange="selectSeries()"/>
</div>
|
清单 4 中的代码将一些控件添加到图表中。首先有一个下拉框,显示来自 清单 1 的每一个数据系列。将在 init 函数中动态加载此数据。还有一个复选框,允许用户指定是否应该聚集数据,也就是说,是否把 Internet Explorer 的所有版本都添加到一起。
改变这些控件中的一个时,将调用 selectSeries 函数。此函数使用来自 HTML 控件的值以便确定应该使用哪个数据系列。然后,它会查看是否选择了聚集复选框,如果是,则它会对已选择的系列应用 aggregateResults 函数。最后,它通过在图表上调用 updateSeries 方法来更新图表,然后再次调用 render。图 3 显示添加了新控件的扇形图。
图 3. 交互扇形图
现在,在数据用于创建扇形图以前,您可以切换数据系列,甚至应用汇集来转换数据。所有的主题和效果仍然适用,因为它仍然是同一图表。您只是切换该图表使用的数据。如果要查看在任何特定时间点什么浏览器对您的站点最重要,这是很有用的。然而,如果您想查看趋势,如什么浏览器在您的站点上用的更多或更少,扇形图就不是很有用了。让我们看看来自 Dojo 的可以用来查看趋势的不同类型图表。
到目前为止您只看到过扇形图,因为它们为您正在使用的数据种类提供良好的可视性 — 显示给定月份中浏览器的相对份额。要显示趋势数据,也就是说,多个月内的数据,您需要一种不同类型的图表。线性图表似乎是一个显而易见的选择。然而,您将需要转换您的数据以使其更适合此种类型的图表。清单 5 显示了转换代码。
清单 5. 趋势分析的数据转换代码
var xStats = {};
function calcStats(){
var i = 0;
var mStats = null;
var browser = "";
var total = 0;
for (i=0;i<stats.length;i++){
mStats = (stats[i]).data;
total = 0;
for (browser in mStats){
total += mStats[browser];
}
for (browser in mStats){
if (!xStats[browser]){
xStats[browser] = [];
}
xStats[browser].push(mStats[browser] / total);
}
}
}
dojo.addOnLoad(calcStats);
|
在 清单 5 中要做的第一件事是为存储新的数据创建名为 xStats 的全局变量。然后,定义一个名为 calcStats 的函数,此函数用来执行必要的转换。此函数在每个月的数据中迭代。它首先汇总该月的总浏览器点击数。然后再次在浏览器中迭代,计算该月浏览器的市场份额,并将其添加到 xStats。最后,xStats 将成为一个映射,其键是浏览器,而其值是浏览器市场份额的数组,所涉及的范围是该浏览从一月到六月的数据。这正是您需要的用于趋势分析的历史数据。最后,进行另一个调用,即 dojo.addOnLoad,以便在启动时执行此函数。现在您只需要将其转变为图表。清单 6 显示了您如何创建显示此数据的线性图表。
清单 6. 创建趋势数据的线性图表
dojo.require("dojox.charting.widget.Legend");
function makeTrends(){
var chart = new dojox.charting.Chart2D("trends");
chart.addPlot("default", {
type: "Lines",
markers : true,
tension : "S",
lines : true,
labelOffset : -30,
shadows : {dx:2, dy:2, dw:2}
});
chart.addAxis("x");
chart.addAxis("y", {vertical:true});
var browser = "";
for (browser in xStats){
chart.addSeries(browser, makeSeries(xStats[browser]));
}
chart.setTheme(dojox.charting.themes.Shrooms);
chart.render();
var legend = new dojox.charting.widget.Legend({chart: chart},
"legend");
}
function makeSeries(data){
var series = [];
var i = 1;
for (var key in data){
series.push({x: i++, y :data[key]});
}
return series;
}
dojo.addOnLoad(makeTrends);
<div id="trends" style="width: 800px; height: 800px;"></div>
<div id="legend"></div>
|
再一次通过添加新的 Dojo 依赖性开始您的代码。这一次它是 dojox.charting.widget.Legend 对象(稍后介绍此对象)。下一步,您要创建一个名为 makeTrends 的函数,此函数将创建新的图表。这类似于创建扇形图的代码。这一次您将拥有不同类型的 Lines。有几个专门用于线性图表的折线图选项,如标记(显示数据点)、张力(使直线弯曲)和阴影(给每条线一个下拉阴影)。请注意您还要添加两个轴,即创建所谓的 x 轴和 y 轴。然后,您要为每一个存储在 xStats 对象中的浏览器添加一个系列。对于每一个浏览器来说,您都要调用 makeSeries 函数。这基本上可将数据转换成 (x,y) 对,此处 x 是月份(1 = 一月、2 = 二月,等等),而 y 是浏览器的市场份额,如该月的百分比。返回到 makeTrends,调用 setTheme 方法,再次使用 Shrooms,然后调用 render。最后,您要使用之前提到的 Legend 对象来创建一个图例。图 4 显示了结果。
图 4. 数据趋势图表
通过此图表,您可以看到 Firefox® 3.5 和 Internet Explorer® 8 等随时间推移而增加了市场份额,而旧版本的 Internet Explorer 和 Firefox 正在逐渐减少。您可以使用此代码试验其他许多图表类型。例如,StackedLines 类型也非常有意思。您也可以合并之前显示的一些技术,如变更数据系列(例如,添加聚集视图等)。
本文已经向您显示了使用 Dojo 工具包创建互动图表的基础。您仅仅看到了 Dojo 支持的诸多图表类型中的两种。许多类型都具有多个独特的功能,这些功能可用于使图表真正具有视觉吸引力。看一下来自 Dojo 的文档以便查看您可以使用什么选项为您的报告应用程序创建最引人注目的图表。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 本文源代码 | reports.zip | 3KB | HTTP |
学习
-
“编写自定义 Dojo 应用程序”(Wendi Nusbickel 和 Melissa Betancourt,developerWorks,2008 年 12 月):了解更多有关 Dojo 的信息。
-
“使用 Dojo 开发 HTML 小部件”(Igor Kusakov,developerWorks,2006 年 10 月):探索 Dojo 的可扩展性。
-
“用 Hadoop 进行分布式数据处理,第 1 部分:入门”和 用 Hadoop 进行分布式数据处理,第 2 部分:进阶(M. Tim Jones,developerWorks,2010 年 5 月):要获得更多 Hadoop 的详细研究,请查看这些文章。
- “用 Big Data 挖掘新的业务洞察”(Stephen Watt,developerWorks,2010 年 6 月):查看 Hadoop 如何将洞察力提供到您的业务中。
-
“使用 Linux 和 Hadoop 进行分布式计算”(Ken Mann 和 M. Tim Jones,developerWorks,2008 年 12 月):了解有关 Hadoop 内部工作的更多信息。
- developerWorks developerWorks 中国网站 Web 开发专区 包含各种基于 web 的解决方案的相关文章。
获得产品和技术
- 获得 Apache Hadoop。本文使用 0.20 版。
- 获得 Java SDK。本文使用 JDK 1.6.0_17。
-
Google Libraries API:使用 Google 的 Ajax API 来下载 Dojo 到您的页面。
- 查看建立在 Hadoop 之上的 Pig 和 Hive 框架。
- 下载 IBM 产品评估试用版软件,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
讨论
- 现在就创建您的 developerWorks 社区配置文件 并在 Hadoop 上 建立查看列表。获得并保持与 developerWorks 社区 的连接。
- 发现其他 对 web 开发感兴趣的 developerWorks 成员。
- Web 开发人员,在 web 开发组中共享您的经验和知识。
- 共享您所知道的:加入专注于 web 主题的 developerWorks 组中的一个。
- Roland Barcia 在其博客中谈论 Web 2.0 和中间件。
- 遵循 developerWorks 成员 在 web 主题上的共享书签。
- 要快速获得答案:请访问 Web 2.0 应用程序论坛。
