本篇的思想:对 HDFS 获取的数据进行两种不同的可视化图表处理方式。第一种 JFreeChar 可视化处理生成图片文件查看。第二种 AJAX+JSON+ECharts 实现可视化图表,并呈现于浏览器上。
对此,给出代码示例,通过网络爬虫技术,将上传到 HDFS 的新浪网新闻信息实现热词统计功能,通过图表的柱状图来显示出来。
------>
目录:
1、JFreeChart 可视化处理(生成本地图片)
【1】HDFS 文件读取
【2】JDFreeChart 库应用
2、AJAX+JSON+EChart 生成可视化图表(网页呈现图表)
【1】EChart 基本方法
【2】JSON 数据格式
【3】AJAX 技术
【4】热词统计示例
3、总结
------>
1、JFreeChart 可视化处理
【1】HDFS 文件读取
保存时,我们数据使用了两种方式保存:
1) 纯文本方式:适合整体读取数据,并按行将内容读取出来处理。
2) MapFileFormat 的方式:适合按 key 来查找 value
这里可以使用 FSDataInputStream 来直接读入文本方式的数据。
代码呈现:
- public class TestReadData {
- public static void main(String[] args) throws Exception {
- Configuration conf = new Configuration();
- FileSystem fs = null;
- Path path = new Path("hdfs://localhost:9000/output/part-00000");
- fs = path.getFileSystem(conf);
- FSDataInputStream is = fs.open(path);
- // 使用一个缓冲流或者内存流来整体读入数据
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String line = null;
- while ((line = br.readLine()) != null) {
- String[] strs = line.split("\t");
- System.out.println(strs[0] + " --> " + strs[1]);
- }
- }
- }
下面我们想从这些词里提取出出现频率最高的 10 个词。
这里就需要使用插入排序的方法来完成。
因此我们这里编写一个工具类,来帮助我们完成排序功能。
同时,为了方便进行对象的保存和传递,建议编写一个 vo 类来保存关键字和出现次数。
代码呈现:
- public class MyKeyValue {
- private String key;
- private Integer value;
- public MyKeyValue() {}
- public MyKeyValue(String key, Integer value) {
- this.key = key;
- this.value = value;
- }
- public String getKey() {
- return key;
- }
- public void setKey(String key) {
- this.key = key;
- }
- public Integer getValue() {
- return value;
- }
- public void setValue(Integer value) {
- this.value = value;
- }
- public int compare(MyKeyValue other) {
- if (this.value >= other.value) {
- return 1;
- } else {
- return - 1;
- }
- }
- }
此时需要修改 TestReadData 类,添加 vo 对象,以及排除一些热词:
- public class TestReadData {
- private static Set < String > allNoKeyword = new HashSet < >();
- static {
- allNoKeyword.add("新闻");
- allNoKeyword.add("新浪网");
- allNoKeyword.add("新浪");
- allNoKeyword.add("聚合");
- allNoKeyword.add("中国");
- allNoKeyword.add("视频");
- allNoKeyword.add("图片");
- allNoKeyword.add("图集");
- allNoKeyword.add("最新");
- allNoKeyword.add("阅读");
- }
- public static void main(String[] args) throws Exception {
- Configuration conf = new Configuration();
- FileSystem fs = null;
- Path path = new Path("hdfs://localhost:9000/output/part-00000");
- fs = path.getFileSystem(conf);
- FSDataInputStream is = fs.open(path);
- // 使用一个缓冲流或者内存流来整体读入数据
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String line = null;
- // 建立工具类
- ValueSortList list = new ValueSortList();
- while ((line = br.readLine()) != null) {
- String[] strs = line.split("\t");
- // 建立vo对象
- if (!allNoKeyword.contains(strs[0]) && strs[0].length() > 1) {
- MyKeyValue keyValue = new MyKeyValue(strs[0], Integer.parseInt(strs[1]));
- list.add(keyValue);
- }
- }
- System.out.println(list);
- }
- }
【2】JFreeChart 库应用
JFreeChart 是由 Java 提供的免费不开源的数据可视化的库。
首先将支持包加入到项目中。
之后可以通过以下固定的步骤,来根据数据,生成图表。
1) 创建数据集合
2) 向集合中添加数据
3) 建立图表对象(根据需要选择不同的图表)
4) 设置图表的参数
5) 将图表输出
饼状图(这里还支持环状和 3D 效果):
- public class PieDemo {
- public static void main(String[] args) throws Exception {
- // 数据集
- DefaultPieDataset dataset = new DefaultPieDataset();
- // 添加数据
- ValueSortList list = TestReadData.getValues();
- for (MyKeyValue keyValue: list.getList()) {
- dataset.setValue(keyValue.getKey(), keyValue.getValue());
- }
- // 创建对象
- JFreeChart chart = ChartFactory.createPieChart("新浪新闻热词分析", dataset, true, true, false);
- // 设置属性
- // 输出
- ChartUtilities.saveChartAsPNG(new File("E:/pie.png"), chart, 500, 500);
- }
- }
柱状图和线型图:(还支持线、3D 柱、3D 线、区域)
- public class BarDemo {
- public static void main(String[] args) throws Exception {
- DefaultCategoryDataset dataset = new DefaultCategoryDataset();
- ValueSortList list = TestReadData.getValues();
- for (MyKeyValue keyValue: list.getList()) {
- dataset.addValue(keyValue.getValue(), keyValue.getKey(), "");
- }
- JFreeChart chart = ChartFactory.createBarChart("热词分析", "词", "次数", dataset, PlotOrientation.VERTICAL, true, true, false);
- ChartUtilities.saveChartAsPNG(new File("E:/bar.png"), chart, 1000, 500);
- }
- }
2、AJAX+JSON+ECharts 生成可视化图表
【1】ECharts 基本使用
ECharts 最早是有一些开源的工程师来开发的免费使用的图表工具,在 1 和 2 版本时都是放在 github 上。之后 ECharts 被百度投资收购,加入了百度的开源产品中。
如果想使用 ECharts 这种的开源工具,必须先去其官网下载开发包。
下载时,建议将完整版和开发版都下载下来,开发版用于开发时进行调试,完整版用于上线提升性能。
下面就需要了解怎样完成一个简单的 ECharts 图表(此也为官网给出的代码示例)。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Document
- </title>
- <script type="text/javascript" src="echarts.js">
- </script>
- <script type="text/javascript">
- function initChart() {
- // 初始化要显示的图标div
- var myChart = echarts.init(document.getElementById('my_chart'));
- var option = {
- title: {
- text: 'ECharts 入门示例'
- },
- tooltip: {
- trigger: "axis",
- label: "销量"
- },
- legend: {
- data: ['销量', '价格']
- },
- xAxis: {
- data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
- },
- yAxis: {},
- series: [{
- name: '销量',
- type: 'bar',
- data: [5, 20, 36, 10, 10, 20]
- },
- {
- name: '价格',
- type: 'line',
- data: [30, 40, 32, 15, 80, 30]
- }]
- };
- myChart.setOption(option);
- }
- </script>
- </head>
- <body onload="initChart();">
- <div id="my_chart" style="width:600px;height:400px;">
- </div>
- </body>
- </html>
【2】JSON 数据格式
JSON:JavaScript Object Notation,是 ECMAScript 的标准语法
这个语法是现在所有 AJAX 或者说数据传输的最常用的语法格式。
使用该语法的原因是语法格式简单,没有关键字来干扰或者占用内存。
解析时各种语言都有很容易的解析方法。
特别是 JavaScript,可以直接通过自带的 eval() 方法来完成字符串转换对象或数组的操作。
JSON 语法很简单:
1) 对象:{}
a) 属性: 属性名: 属性值,多个属性之间逗号分隔
b) 方法: 方法名: function(){}
2) 数组:[]
a) 每个元素使用逗号分隔。
【3】AJAX 技术
AJAX:Asynchronous JavaScript And Xml,异步的 JavaScript 和 XML,不是新技术,是基于 JS 和 XML 技术的应用,但是现在 XML 一般都被 JSON 替代了,所以实际上 AJAX 已经变成了纯 JS 的技术了。
通过 AJAX 技术,可以在页面不刷新的情况下,让前端沟通后台来获取数据,数据通过 JSON 格式来返回进行处理。
这样前后台分离就更彻底了,后台只需要专注于后台接口的开发即可,通过接口返回 JSON 数据。
前台则是接收了返回的数据后,根据数据完成各种页面效果的展示。
AJAX 技术已经很成熟了,通过固定的 4 个步骤就可以沟通后台接收结果。
1、 建立核心配置对象 XMLHttpRequest
2、 建立与后台的连接
3、 设置返回时的回调函数
当后台执行完结果返回数据时,前台必须有个方法可以接收这个数据,并进行处理,这个方法就是回调函数(Callback)
【4】热词统计生成可视化图表
基于 ECharts,我们来把热词统计功能,通过这个 ECharts 图表的柱状图来显示出来。
- var xmlHttp;
- function createXMLHttp() {
- if (window.XMLHttpRequest != null) {
- xmlHttp = new XMLHttpRequest();
- } else {
- xmlHttp = new ActiveXObject("Microsoft.xmlhttp");
- }
- }
- function initChart() {
- // 初始化要显示的图标div
- var myChart = echarts.init(document.getElementById('my_chart'));
- // 这里就需要通过AJAX技术,来调用后台数据操作,接收返回的JSON格式数据
- // 1
- createXMLHttp();
- // 2
- xmlHttp.open("get", "<%=basePath%>ajax.do");
- // 3
- xmlHttp.onreadystatechange = chartCallback;
- // 4
- xmlHttp.send();
- }
- function chartCallback() {
- }
之后,需要在后台的 ajax.do 中进行 HDFS 的操作,将需要的数据取得,并通过 JSON 的格式来返回页面。
- @RequestMapping(value = "/ajax.do")
- public void ajax(HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- // 读取HDFS中的文本数据
- ValueSortList list = HDFSUtils.getValues();
- StringBuilder builder = new StringBuilder(
- "{ title: {text: '新浪新闻热词分析'},tooltip: {trigger:'axis'},");
- builder.append("legend: {data:['词频']},xAxis: {data: [");
- StringBuilder tempSeries = new StringBuilder();
- tempSeries.append("series: [{name:'词频',type:'bar',data:[");
- for (MyKeyValue kv : list.getList()) {
- builder.append("'");
- builder.append(kv.getKey());
- builder.append("',");
- tempSeries.append(kv.getValue());
- tempSeries.append(",");
- }
- // 需要把最后一段截取掉
- String resultStr = builder.substring(0, builder.length() - 1)
- + "]}, yAxis: {},";
- resultStr += tempSeries.substring(0, tempSeries.length() - 1) + "]}]}";
- // 结果返回需要通过PrintWriter来输出
- // 需要先处理返回乱码
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.print(resultStr);
- writer.close();
- }
之后编写页面回调函数就可以显示图表了。
- function chartCallback() {
- // 判断结果是否真正返回
- if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
- var resultStr = xmlHttp.responseText;
- // 转换为对象
- var option = eval("(" + resultStr + ")");
- myChart.setOption(option);
- }
- }
但是我们会发现,拼写 JSON 字符串太麻烦了,因此实际开发中会有很多 java 用的 json 数据处理的库,可以帮助我们简单的拼写出 json 字符串。
例如:org.json
- @RequestMapping(value = "/ajax.do") public void ajax(HttpServletRequest request, HttpServletResponse response) throws Exception {
- // 读取HDFS中的文本数据
- ValueSortList list = HDFSUtils.getValues();
- JSONObject obj = new JSONObject();
- JSONObject titleObj = new JSONObject();
- titleObj.put("text", "新浪新闻热词分析");
- obj.put("title", titleObj);
- JSONObject tooltipsObj = new JSONObject();
- tooltipsObj.put("trigger", "axis");
- obj.put("tooltip", tooltipsObj);
- JSONObject legendObj = new JSONObject();
- legendObj.put("data", "词频");
- obj.put("legend", legendObj);
- obj.put("yAxis", new JSONObject());
- JSONObject xObj = new JSONObject();
- JSONArray seArr = new JSONArray();
- JSONObject seObj = new JSONObject();
- seObj.put("name", "词频");
- seObj.put("type", "bar");
- JSONArray xDataArr = new JSONArray();
- JSONArray seDataArr = new JSONArray();
- for (MyKeyValue kv: list.getList()) {
- xDataArr.put(kv.getKey());
- seDataArr.put(kv.getValue());
- }
- xObj.put("data", xDataArr);
- seObj.put("data", seDataArr);
- seArr.put(seObj);
- obj.put("xAxis", xObj);
- obj.put("series", seArr);
- // 结果返回需要通过PrintWriter来输出
- // 需要先处理返回乱码
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.print(obj.toString());
- writer.close();
- }
对于这种热词分析,前台最好的展示方式应该是文字云,因此我们这里直接使用文字云的插件来完成。
首先也要导入 js 文件。
- <script type="text/javascript" src="echarts/echarts.js">
- </script>
- <script type="text/javascript" src="echarts/echarts-wordcloud.js">
- </script>
- <script type="text/javascript">
- var xmlHttp;
- var myChart;
- var option;
- function createXMLHttp() {
- if (window.XMLHttpRequest != null) {
- xmlHttp = new XMLHttpRequest();
- } else {
- xmlHttp = new ActiveXObject("Microsoft.xmlhttp");
- }
- }
- function initChart() {
- // 初始化要显示的图标div
- myChart = echarts.init(document.getElementById('my_chart'));
- option = {
- tooltip: {},
- series: [{
- type: 'wordCloud',
- gridSize: 2,
- sizeRange: [12, 50],
- rotationRange: [ - 90, 90],
- shape: 'pentagon',
- width: 600,
- height: 400,
- drawOutOfBound: true,
- textStyle: {
- normal: {
- color: function() {
- return 'rgb(' + [Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160)].join(',') + ')';
- }
- },
- emphasis: {
- shadowBlur: 10,
- shadowColor: '#333'
- }
- }
- }]
- };
- // 这里就需要通过AJAX技术,来调用后台数据操作,接收返回的JSON格式数据
- // 1
- createXMLHttp();
- // 2
- xmlHttp.open("get", "<%=basePath%>ajax_cloud.do");
- // 3
- xmlHttp.onreadystatechange = chartCallback;
- // 4
- xmlHttp.send();
- }这里为了简化后台拼写JSON,将固定的内容提前设置到option对象中。
之后在后台完成数据的拼写。
- @RequestMapping(value="/ajax_cloud.do")
- public void ajaxCloud(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- ValueSortList list = HDFSUtils.getValues();
- JSONArray array = new JSONArray();
- for (MyKeyValue kv : list.getList()) {
- JSONObject obj = new JSONObject();
- obj.put("name", kv.getKey());
- obj.put("value", kv.getValue());
- array.put(obj);
- }
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.print(array.toString());
- writer.close();
- }
最后在回调函数中进行设置处理。
- function chartCallback() {
- // 判断结果是否真正返回
- if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
- var resultStr = xmlHttp.responseText;
- // 转换为对象
- option.series[0].data = eval("(" + resultStr + ")");
- myChart.setOption(option);
- }
- }
结果呈现(柱状图):
总结:
从前面阐述的网络爬虫、HDFS 数据读取、MR 数据分析、Lucene 垂直搜索引擎,到现在的可视化图表呈现,一个简单的大数据处理框架也渐浮水面。
1、数据获取数据记录
2、提取清洁数据标注
3、整合聚集数据表达
4、建立模型数据分析
5、合理解释可视化
虽然并不如真正的大数据处理的数据量之大、之复杂,可视化的程度也仅限于热词统计,不过既然授之以渔,而且也算是对此有了一个基本的了解了。
关于本篇给出的两种可视化处理方法,其实还有很多方式。我只阐述了 EFreeChart 和 ECharts 两种方式,一种生成本地图片文件类型,一种结合 AJAX+JSON 可以在网页上呈现可视化图表。不过见解很浅薄,仅借本文能够让未知的读者实现一个简单的图表展现方式,给内功深厚的高手淡然一笑,我也就心满意足了。
来源: http://www.cnblogs.com/1996swg/p/7392697.html