zoukankan      html  css  js  c++  java
  • JFreeChart与AJAX+JSON+ECharts两种处理方式生成热词统计可视化图表

    本篇的思想:对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来直接读入文本方式的数据。

    代码呈现:

     1 public class TestReadData {
     2 
     3     public static void main(String[] args) throws Exception {
     4         Configuration conf = new Configuration();
     5         FileSystem fs = null;
     6         Path path = new Path("hdfs://localhost:9000/output/part-00000");
     7         fs = path.getFileSystem(conf);
     8         FSDataInputStream is = fs.open(path);
     9         // 使用一个缓冲流或者内存流来整体读入数据
    10         BufferedReader br = new BufferedReader(new InputStreamReader(is));
    11         String line = null;
    12         while ((line = br.readLine()) != null) {
    13             String[] strs = line.split("	");
    14             System.out.println(strs[0] + " --> " + strs[1]);
    15         }
    16     }
    17 }

    下面我们想从这些词里提取出出现频率最高的10个词。

    这里就需要使用插入排序的方法来完成。

    因此我们这里编写一个工具类,来帮助我们完成排序功能。

    同时,为了方便进行对象的保存和传递,建议编写一个vo类来保存关键字和出现次数。

    代码呈现:

     1 public class MyKeyValue {
     2 
     3     private String key;
     4     private Integer value;
     5 
     6     public MyKeyValue() {
     7     }
     8 
     9     public MyKeyValue(String key, Integer value) {
    10         this.key = key;
    11         this.value = value;
    12     }
    13 
    14     public String getKey() {
    15         return key;
    16     }
    17 
    18     public void setKey(String key) {
    19         this.key = key;
    20     }
    21 
    22     public Integer getValue() {
    23         return value;
    24     }
    25 
    26     public void setValue(Integer value) {
    27         this.value = value;
    28     }
    29 
    30     public int compare(MyKeyValue other) {
    31         if (this.value >= other.value) {
    32             return 1;
    33         } else {
    34             return -1;
    35         }
    36     }
    37 }

    此时需要修改TestReadData类,添加vo对象,以及排除一些热词:

     1 public class TestReadData {
     2 
     3     private static Set<String> allNoKeyword = new HashSet<>();
     4 
     5     static {
     6         allNoKeyword.add("新闻");
     7         allNoKeyword.add("新浪网");
     8         allNoKeyword.add("新浪");
     9         allNoKeyword.add("聚合");
    10         allNoKeyword.add("中国");
    11         allNoKeyword.add("视频");
    12         allNoKeyword.add("图片");
    13         allNoKeyword.add("图集");
    14         allNoKeyword.add("最新");
    15         allNoKeyword.add("阅读");
    16     }
    17 
    18     public static void main(String[] args) throws Exception {
    19         Configuration conf = new Configuration();
    20         FileSystem fs = null;
    21         Path path = new Path("hdfs://localhost:9000/output/part-00000");
    22         fs = path.getFileSystem(conf);
    23         FSDataInputStream is = fs.open(path);
    24         // 使用一个缓冲流或者内存流来整体读入数据
    25         BufferedReader br = new BufferedReader(new InputStreamReader(is));
    26         String line = null;
    27         // 建立工具类
    28         ValueSortList list = new ValueSortList();
    29         while ((line = br.readLine()) != null) {
    30             String[] strs = line.split("	");
    31             // 建立vo对象
    32             if (!allNoKeyword.contains(strs[0]) && strs[0].length() > 1) {
    33                 MyKeyValue keyValue = new MyKeyValue(strs[0],
    34                         Integer.parseInt(strs[1]));
    35                 list.add(keyValue);
    36             }
    37         }
    38 
    39         System.out.println(list);
    40     }
    41 }

    【2】JFreeChart库应用

    JFreeChart是由Java提供的免费不开源的数据可视化的库。

    首先将支持包加入到项目中。

    之后可以通过以下固定的步骤,来根据数据,生成图表。

    1) 创建数据集合

    2) 向集合中添加数据

    3) 建立图表对象(根据需要选择不同的图表)

    4) 设置图表的参数

    5) 将图表输出

    饼状图(这里还支持环状和3D效果):

     1 public class PieDemo {
     2        
     3     public static void main(String[] args) throws Exception {
     4         // 数据集
     5         DefaultPieDataset dataset = new DefaultPieDataset();
     6 
     7         // 添加数据
     8         ValueSortList list = TestReadData.getValues();
     9 
    10         for (MyKeyValue keyValue : list.getList()) {
    11             dataset.setValue(keyValue.getKey(), keyValue.getValue());
    12         }
    13 
    14         // 创建对象
    15         JFreeChart chart = ChartFactory.createPieChart("新浪新闻热词分析", dataset,
    16                 true, true, false);
    17 
    18         // 设置属性
    19 
    20         // 输出
    21         ChartUtilities.saveChartAsPNG(new File("E:/pie.png"), chart, 500, 500);
    22 
    23     }
    24 
    25 }

    柱状图和线型图:(还支持线、3D柱、3D线、区域)

     1 public class BarDemo {
     2 
     3     public static void main(String[] args) throws Exception {
     4         DefaultCategoryDataset dataset = new DefaultCategoryDataset();
     5 
     6         ValueSortList list = TestReadData.getValues();
     7 
     8         for (MyKeyValue keyValue : list.getList()) {
     9             dataset.addValue(keyValue.getValue(), keyValue.getKey(), "");
    10         }
    11 
    12         JFreeChart chart = ChartFactory.createBarChart("热词分析", "词", "次数",
    13                 dataset, PlotOrientation.VERTICAL, true, true, false);
    14 
    15         ChartUtilities.saveChartAsPNG(new File("E:/bar.png"), chart, 1000, 500);
    16 
    17     }
    18 }

    2、AJAX+JSON+ECharts生成可视化图表

    【1】ECharts基本使用

    ECharts最早是有一些开源的工程师来开发的免费使用的图表工具,在 1 2版本时都是放在github上。之后ECharts被百度投资收购,加入了百度的开源产品中。

    如果想使用ECharts这种的开源工具,必须先去其官网下载开发包。

    下载时,建议将完整版和开发版都下载下来,开发版用于开发时进行调试,完整版用于上线提升性能。

    下面就需要了解怎样完成一个简单的ECharts图表(此也为官网给出的代码示例)。

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Document</title>
     6     <script type="text/javascript" src="echarts.js"></script>
     7     <script type="text/javascript">
     8         function initChart() {
     9             // 初始化要显示的图标div
    10             var myChart = echarts.init(document.getElementById('my_chart'));
    11             var option = {
    12                 title: {
    13                     text: 'ECharts 入门示例'
    14                 },
    15                 tooltip: {
    16                     trigger:"axis",
    17                     label:"销量"
    18                 },
    19                 legend: {
    20                     data:['销量','价格']
    21                 },
    22                 xAxis: {
    23                     data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
    24                 },
    25                 yAxis: {},
    26                 series: [{
    27                     name: '销量',
    28                     type: 'bar',
    29                     data: [5, 20, 36, 10, 10, 20]
    30                 },{
    31                     name: '价格',
    32                     type: 'line',
    33                     data: [30, 40, 32, 15, 80, 30]
    34                 }]
    35             };
    36 
    37             myChart.setOption(option);
    38         }
    39 
    40     </script>
    41 </head>
    42 <body onload="initChart();">
    43     
    44     <div id="my_chart" style="600px;height:400px;"></div>
    45 
    46 </body>
    47 </html>

    【2】JSON数据格式

    JSONJavaScript Object Notation,是ECMAScript的标准语法

    这个语法是现在所有AJAX或者说数据传输的最常用的语法格式。

    使用该语法的原因是语法格式简单,没有关键字来干扰或者占用内存。

    解析时各种语言都有很容易的解析方法。

    特别是JavaScript,可以直接通过自带的eval()方法来完成字符串转换对象或数组的操作。

    JSON语法很简单:

    1) 对象:{}

      a) 属性: 属性名:属性值,多个属性之间逗号分隔

      b) 方法: 方法名:function(){}

    2) 数组:[]

      a) 每个元素使用逗号分隔。

    【3】AJAX技术

    AJAXAsynchronous JavaScript And Xml,异步的JavaScriptXML,不是新技术,是基于JSXML技术的应用,但是现在XML一般都被JSON替代了,所以实际上AJAX已经变成了纯JS的技术了。

    通过AJAX技术,可以在页面不刷新的情况下,让前端沟通后台来获取数据,数据通过JSON格式来返回进行处理。

    这样前后台分离就更彻底了,后台只需要专注于后台接口的开发即可,通过接口返回JSON数据。

    前台则是接收了返回的数据后,根据数据完成各种页面效果的展示。

    AJAX技术已经很成熟了,通过固定的4个步骤就可以沟通后台接收结果。

    1、 建立核心配置对象XMLHttpRequest

    2、 建立与后台的连接

    3、 设置返回时的回调函数

    当后台执行完结果返回数据时,前台必须有个方法可以接收这个数据,并进行处理,这个方法就是回调函数(Callback

    【4】热词统计生成可视化图表

    基于ECharts,我们来把热词统计功能,通过这个ECharts图表的柱状图来显示出来。

     1         var xmlHttp ;
     2         
     3         function createXMLHttp() {
     4             if (window.XMLHttpRequest != null) {
     5                 xmlHttp = new XMLHttpRequest();
     6             } else {
     7                 xmlHttp = new ActiveXObject("Microsoft.xmlhttp");
     8             }
     9         }
    10     
    11         function initChart() {
    12             // 初始化要显示的图标div
    13             var myChart = echarts.init(document.getElementById('my_chart'));
    14             
    15             // 这里就需要通过AJAX技术,来调用后台数据操作,接收返回的JSON格式数据
    16             // 1
    17             createXMLHttp();
    18             // 2
    19             xmlHttp.open("get","<%=basePath%>ajax.do");
    20             // 3
    21             xmlHttp.onreadystatechange = chartCallback;
    22             // 4
    23             xmlHttp.send();
    24         }
    25         
    26         function chartCallback() {
    27             
    28         }

     之后,需要在后台的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();
        }

    之后编写页面回调函数就可以显示图表了。

    1         function chartCallback() {
    2             // 判断结果是否真正返回
    3             if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
    4                 var resultStr = xmlHttp.responseText;
    5                 // 转换为对象
    6                 var option = eval("("+resultStr+")");
    7                 myChart.setOption(option);
    8             }
    9         }

    但是我们会发现,拼写JSON字符串太麻烦了,因此实际开发中会有很多java用的json数据处理的库,可以帮助我们简单的拼写出json字符串

    例如:org.json

     1     @RequestMapping(value = "/ajax.do")
     2     public void ajax(HttpServletRequest request, HttpServletResponse response)
     3             throws Exception {
     4         // 读取HDFS中的文本数据
     5         ValueSortList list = HDFSUtils.getValues();
     6 
     7         JSONObject obj = new JSONObject();
     8         
     9 
    10         JSONObject titleObj = new JSONObject();
    11         titleObj.put("text", "新浪新闻热词分析");
    12         obj.put("title", titleObj);
    13 
    14         JSONObject tooltipsObj = new JSONObject();
    15         tooltipsObj.put("trigger", "axis");
    16         obj.put("tooltip", tooltipsObj);
    17 
    18         JSONObject legendObj = new JSONObject();
    19         legendObj.put("data", "词频");
    20         obj.put("legend", legendObj);
    21 
    22         obj.put("yAxis", new JSONObject());
    23 
    24         JSONObject xObj = new JSONObject();
    25         JSONArray seArr = new JSONArray();
    26         JSONObject seObj = new JSONObject();
    27         seObj.put("name", "词频");
    28         seObj.put("type", "bar");
    29         JSONArray xDataArr = new JSONArray();
    30         JSONArray seDataArr = new JSONArray();
    31 
    32         for (MyKeyValue kv : list.getList()) {
    33             xDataArr.put(kv.getKey());
    34             seDataArr.put(kv.getValue());
    35         }
    36 
    37         xObj.put("data", xDataArr);
    38         seObj.put("data", seDataArr);
    39         seArr.put(seObj);
    40 
    41         obj.put("xAxis", xObj);
    42         obj.put("series", seArr);
    43 
    44         // 结果返回需要通过PrintWriter来输出
    45         // 需要先处理返回乱码
    46         response.setCharacterEncoding("UTF-8");
    47         response.setContentType("text/html");
    48         PrintWriter writer = response.getWriter();
    49         writer.print(obj.toString());
    50         writer.close();
    51     }

    对于这种热词分析,前台最好的展示方式应该是文字云,因此我们这里直接使用文字云的插件来完成。

    首先也要导入js文件。

     1 <script type="text/javascript" src="echarts/echarts.js"></script>
     2 <script type="text/javascript" src="echarts/echarts-wordcloud.js"></script>
     3 <script type="text/javascript">
     4         var xmlHttp ;
     5         
     6         var myChart ;
     7         
     8         var option ;
     9         
    10         function createXMLHttp() {
    11             if (window.XMLHttpRequest != null) {
    12                 xmlHttp = new XMLHttpRequest();
    13             } else {
    14                 xmlHttp = new ActiveXObject("Microsoft.xmlhttp");
    15             }
    16         }
    17     
    18         function initChart() {
    19             // 初始化要显示的图标div
    20             myChart = echarts.init(document.getElementById('my_chart'));
    21             
    22             option = {
    23                     tooltip: {},
    24                     series: [{
    25                         type: 'wordCloud',
    26                         gridSize: 2,
    27                         sizeRange: [12, 50],
    28                         rotationRange: [-90, 90],
    29                         shape: 'pentagon',
    30                          600,
    31                         height: 400,
    32                         drawOutOfBound: true,
    33                         textStyle: {
    34                             normal: {
    35                                 color: function () {
    36                                     return 'rgb(' + [
    37                                         Math.round(Math.random() * 160),
    38                                         Math.round(Math.random() * 160),
    39                                         Math.round(Math.random() * 160)
    40                                     ].join(',') + ')';
    41                                 }
    42                             },
    43                             emphasis: {
    44                                 shadowBlur: 10,
    45                                 shadowColor: '#333'
    46                             }
    47                         }
    48                     }]
    49             };
    50             
    51             // 这里就需要通过AJAX技术,来调用后台数据操作,接收返回的JSON格式数据
    52             // 1
    53             createXMLHttp();
    54             // 2
    55             xmlHttp.open("get","<%=basePath%>ajax_cloud.do");
    56             // 3
    57             xmlHttp.onreadystatechange = chartCallback;
    58             // 4
    59             xmlHttp.send();
    60         }
    61 这里为了简化后台拼写JSON,将固定的内容提前设置到option对象中。

    之后在后台完成数据的拼写。

     1     @RequestMapping(value="/ajax_cloud.do")
     2     public void ajaxCloud(HttpServletRequest request,
     3             HttpServletResponse response) throws Exception {
     4         ValueSortList list = HDFSUtils.getValues();
     5 
     6         JSONArray array = new JSONArray();
     7         for (MyKeyValue kv : list.getList()) {
     8             JSONObject obj = new JSONObject();
     9             obj.put("name", kv.getKey());
    10             obj.put("value", kv.getValue());
    11             array.put(obj);
    12         }
    13         
    14         response.setCharacterEncoding("UTF-8");
    15         response.setContentType("text/html");
    16         PrintWriter writer = response.getWriter();
    17         writer.print(array.toString());
    18         writer.close();
    19     }

    最后在回调函数中进行设置处理。

    1         function chartCallback() {
    2             // 判断结果是否真正返回
    3             if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
    4                 var resultStr = xmlHttp.responseText;
    5                 // 转换为对象
    6                 option.series[0].data = eval("("+resultStr+")");
    7                 myChart.setOption(option);
    8             }
    9         }

    结果呈现(柱状图):

     总结:

      从前面阐述的网络爬虫、HDFS数据读取、MR数据分析、Lucene垂直搜索引擎,到现在的可视化图表呈现,一个简单的大数据处理框架也渐浮水面。

         1、数据获取数据记录

         2、提取清洁数据标注

         3、整合聚集数据表达

         4、建立模型数据分析

         5、合理解释可视化

       虽然并不如真正的大数据处理的数据量之大、之复杂,可视化的程度也仅限于热词统计,不过既然授之以渔,而且也算是对此有了一个基本的了解了。

      关于本篇给出的两种可视化处理方法,其实还有很多方式。我只阐述了EFreeChart和ECharts两种方式,一种生成本地图片文件类型,一种结合AJAX+JSON可以在网页上呈现可视化图表。不过见解很浅薄,仅借本文能够让未知的读者实现一个简单的图表展现方式,给内功深厚的高手淡然一笑,我也就心满意足了。

       

  • 相关阅读:
    在IE和Firfox获取keycode
    using global variable in android extends application
    using Broadcast Receivers to listen outgoing call in android note
    help me!virtual keyboard issue
    using iscroll.js and iscroll jquery plugin in android webview to scroll div and ajax load data.
    javascript:jquery.history.js使用方法
    【CSS核心概念】弹性盒子布局
    【Canvas学习笔记】基础篇(二)
    【JS核心概念】数据类型以及判断方法
    【问题记录】ElementUI上传组件使用beforeupload钩子校验失败时的问题处理
  • 原文地址:https://www.cnblogs.com/1996swg/p/7392697.html
Copyright © 2011-2022 走看看