• 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可以在网页上呈现可视化图表。不过见解很浅薄,仅借本文能够让未知的读者实现一个简单的图表展现方式,给内功深厚的高手淡然一笑,我也就心满意足了。

       

  • 相关阅读:
    ubuntu删除django和安装django
    linux shell 统计文件单词出现次数
    linux shell $$、$!特殊符号
    linux安装zabbix需要php两个模块php-bcmach与php-mbstring
    linux 源码编译与卸载
    Job for dhcpd.service failed because the control process exited with error code. See "systemctl status dhcpd.service" and "journalctl -xe" for details.问题
    Linux中部署DNS分离解析技术
    NFS网络文件系统服务搭建
    Samba服务搭建
    Linux RAID磁盘阵列技术
  • 原文地址:https://www.cnblogs.com/1996swg/p/7392697.html
Copyright © 2020-2023  润新知