hive+R 实现大数据下属性间相关性的热力图展示

hive+R 实现大数据下属性间相关性的热力图展示

这是自己完成的第一个小程序,特将有价值的地方在此记录下来,包括以下几部分内容:

  • Hive数据导入–Sqoop方式
  • Map键值对实现Excel数据透视表的功能
  • Java连接R
  • 将数据存入R的数据框
  • Java调用R函数作图

一、Hive数据导入

Hive数据常见的导入方式主要有四种:
(1)、从本地文件系统中导入数据到Hive表;
(2)、从HDFS上导入数据到Hive表;
(3)、从别的表中查询出相应的数据并导入到Hive表中;
(4)、在创建表的时候通过从别的表中查询出相应的记录并插入到所创建的表中。
这里是选择第三种方式,先将数据导入到本地关系数据库MySql中,然后在Hive中新建相应的表,语句如下:

create table mytable(id string, samaddr string, samno string, class string, time string, year int, month int, day int, norm string, tno int, tname string, value double)row format delimited fields terminated by ’\t’

运用以下Sqoop语句将mysql表中的数据导入到Hive表:

sqoop import –hive-import –connect jdbc:mysql://localhost:3306/mytable –username rootpassword mypassword –table mytable –hive-database mydatabase –hive -table mytable;

二、数据维度转换

由于R分析相关性是针对每一个指标的值进行相关系数分析,然而数据库中所有指标都放在targetNo属性中,其相当于是一维的数据表,需要按每一个数据记录将targetNo中的指标编号重新转换为表的属性,相当于Excel中的数据透视表功能。这里使用Map进行实现,代码如下:

(1).取查询到的数据中所有的指标编号

private List<String> getMyTargetno(JSONArray ja) {
        List<String> targetnos=new ArrayList<String>();
        //保存所有指标编号到String
        for (int i = 0; i < ja.length(); i++) {
            try {
                JSONObject jo = (JSONObject) ja.get(i);
                String stargetno = jo.getString("targetno");
                targetnos.add(stargetno);
                if (i==0 ) {
                        targetnos.add(stargetno);;
                }else {
                    for (int j = i-1; j >=0; j--) {
                        if(stargetno.equals(targetnos.get(j)))
                            break; 
                        else {
                            targetnos.add(stargetno);
                        }   
                        break;
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        List<String> alltargetno = removeDuplicate(targetnos);//去掉重复项
        Collections.sort(alltargetno); //排序
        return alltargetno;
    }

private List<String> removeDuplicate(List<String> list) {
        Set<String> someSet = new HashSet<String>(list);
        // 将Set中的集合,放到一个临时的链表中(tempList)
        Iterator<String> iterator = someSet.iterator();
        List<String> tempList = new ArrayList<String>();
        int i = 0;
        while (iterator.hasNext()) {
            tempList.add(iterator.next().toString());
            i++;
        }
        return tempList;
    }

(2).将数据转为Map键值对集合,然后转存入一个二维表中,实现指标编号的二维化处理:

public Double[][] jsonArrayDataToTwoDArray(JSONArray ja, List<String> myListTargetno, int samnoCount) throws JSONException {

        // 结果集列数
        int columnCount = myListTargetno.size();
        //将所有选取到的指标编号放入二维数组
        Double arr[][] = new Double[columnCount][samnoCount];
        for (int i = 0; i < columnCount; i++){
             arr[i][0] = Double.parseDouble(myListTargetno.get(i));
        }
        Map<String, String> map = new TreeMap<String, String>(//声明具有排序的Map
                new Comparator<String>() {
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });

        int colss = 1;
        for (int i = 0; i < ja.length() && colss<samnoCount; i++) {
            try {
                JSONObject jo = (JSONObject) ja.get(i);
                String ssamno = jo.getString("samno");
                String stargetno = jo.getString("targetno");
                String svalue = jo.getString("value");

                if (i==0) {
                    map.put("ssamno", ssamno);
                    map.put(stargetno, svalue);
                }else if (ssamno.equals(map.get("ssamno"))) {
                    map.put(stargetno, svalue);
                    if (i==ja.length()-1) {//最后一组加入
                        map.remove("ssamno");
                        arr = mapToTwoDArray(map, arr, colss, columnCount);//每取到一个记录中的所有数据,就将其存入二维数组中的一行
                    }
                }else {
                    //根据Map中的某一个key删除该键值对
                    map.remove("ssamno");

                    arr = mapToTwoDArray(map, arr, colss, columnCount);//每取到一个记录中的所有数据,就将其存入二维数组中的一行
                    colss++;

                    map.clear();
                    map.put("ssamno", ssamno);
                    map.put(stargetno, svalue);
                }
             } catch (JSONException e) {
                e.printStackTrace();
             }
        }
        return arr;
    }

    private Double[][] mapToTwoDArray(Map<String, String> map, Double[][] arr, int colss, int columnCount) {
        for (Map.Entry<String, String> entry : map.entrySet()){
            if (entry.getValue()!=null && entry.getValue()!="") {
                for (int rows = 0; rows < columnCount; rows++){
                    if (Double.parseDouble(entry.getKey())==arr[rows][0]) {
                        arr[rows][colss] =  Double.parseDouble("".equals(entry.getValue().toString())?"-100":entry.getValue().toString());

                        break;
                  }
               }
             }
        }
        return arr;
    }

(3).数据处理:将每个指标中大量重复的数据进行删除

private Double[][] myDataHandle(Double[][] jadata) {
        Double[][] my1data = new Double[jadata.length][jadata[0].length];
        int flag = 0;
        for (int i = 0; i < jadata.length; i++) {//删除无效的数据,
            int count =0;
            for (int j = 2; j < jadata[0].length; j++) {
                int flag2 = 0;
                int count1 =0;
                if (jadata[i][j]==null||jadata[i][1]==null){
                    flag2++;
                }else if(jadata[i][j].equals(jadata[i][1+flag2]) ) {
                    count1++;
                }
                count=count+count1+flag2;
            }

            if (count>=jadata[0].length/2 ) {
                flag++;
            }
            if (count<jadata[0].length/2) {

                for (int j = 0; j < jadata[0].length; j++) {
                    my1data[i-flag][j]=jadata[i][j];
                }
            }
        }

        Double[][] wdata = new Double[jadata.length-flag][jadata[0].length];
        if(jadata.length-flag>3){//删除后面的空行
            for (int i = 0; i < wdata.length; i++) {
                for (int j = 0; j < my1data[0].length; j++) {
                    wdata[i][j]=my1data[i][j];
                }
            }
        }else{//如果剩余数据行小于4,则将该二维数组置空
            Double[][] w1data = new Double[0][0];
            wdata = w1data;
        }
        return wdata;
    }

三、运用R进行相关性分析

(1).Java连接R,并初始化一个data用于wdata数据的存入

需要导入的jar包有:

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;

连接R:

RConnection c = new RConnection();
REXP x = c.eval("R.version.string");
c.eval("data<-null");

当然还需要在R中启动服务,R中的语句为:

> library(Rserve)
> Rserve()

(2).将数据遍历存入data中,并将wdata中第一行的指标编号单独取出作为R的data数据框的列名

for (int i = 0; i < jawdata.length; i++) {
                c.eval("data1<--1");
                for (int j = 1; j < jawdata[0].length; j++) {
                    if (i==0 || j==1) {
                        if (jawdata[i][j] == null) {
                            c.eval("data1<--1");
                        } else {
                            if (j!=1) {
                                c.eval("data1<-c(data1," + jawdata[i][j]+")");
                            }else {

                                c.eval("data1<-" + jawdata[i][j]+" ");
                            }
                        }
                    }else {
                        if (jawdata[i][j] == null || jawdata[i][j]==-1) {
                            c.eval("data1<-c(data1,-1)");
                        } else {
                            c.eval("data1<-c(data1," + jawdata[i][j]+")");

                        }
                    }
                }
                if (i==0) {
                    c.eval("data<-data1");
                    c.eval("tnames<-"+jawdata[i][0]+"");
                }else {
                    c.eval("data<-cbind(data,data1)");
                    c.eval("tnames<-c(tnames,"+jawdata[i][0]+")");
                }

    }

(3).调用R画图函数作图

c.eval("colnames(data)<-tnames");//添加数据框属性名
c.eval("library(corrplot)");//加载R包
c.eval("col123 <- colorRampPalette(c('#67001F', '#B2182B', '#D6604D', '#F4A582', '#FDDBC7','#FFFFFF', '#D1E5F0', '#92C5DE', '#4393C3', '#2166AC', '#053061'))");//设置热力图的颜色属性
c.eval("JCort<-cor(data[,c(1,2:ncol(data))],use='pairwise.complete.obs')");//求各个指标之间的相关系数
c.eval("corrplot(JCort, method='color', col=col123(40), cl.length=10, tl.srt=20, order ='hclust',tl.cex=1, addrect=1, addCoef.col='grey',cl.ratio=0.2, cl.align='l')");//对求出的相关系数画热力图

(4).下面展示出画出的其中一张热力图
热力图
提示:颜色和右边[-1,1]区间的数字代表相关性的大小;颜色越深(越接近-1或1)表示相关性越强,反之相关性越弱;越蓝(越接近1)表示正相关越强,越红(越接近-1)表示负相关性越强。

本文只记录了相对比较有价值的地方,代码中也许存在冗余,或者有更好的更方便的实现方法,欢迎大家指正。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页