1. 程式人生 > >JFreeChart與AJAX+JSON+ECharts兩種處理方式生成熱詞統計可視化圖表

JFreeChart與AJAX+JSON+ECharts兩種處理方式生成熱詞統計可視化圖表

線型 static 後臺 標註 png tip 開源工具 grid 讀取

本篇的思想:對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("\t"); 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("\t");
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="width: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                         width: 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可以在網頁上呈現可視化圖表。不過見解很淺薄,僅借本文能夠讓未知的讀者實現一個簡單的圖表展現方式,給內功深厚的高手淡然一笑,我也就心滿意足了。

  

JFreeChart與AJAX+JSON+ECharts兩種處理方式生成熱詞統計可視化圖表