39.Spark大型电商项目-用户访问session分析-session随机抽取之按时间比例随机抽取算法实现

目录

分析

实现

完整代码


本篇文章将介绍用户访问session分析-session随机抽取之按时间比例随机抽取算法实现。

分析

1.处理的数据格式 <yyyy-MM-dd_HH,count>,需要将数据格式转化为<yyyy-MM-dd,<HH,count>>。

2.计算100个session在需要抽取的天数中平均抽取的个数n。

3.在每天的session中根据每个小时所占比例随机抽取各个时间段抽取这个n个session。

实现

1.将<yyyy-MM-dd_HH,count>格式的map,转换为<yyyy-MM-dd,<HH,count>>

      //将<yyyy-MM-dd_HH,count>格式的map,转换为<yyyy-MM-dd,<HH,count>>
        Map<String,Map<String,Long>> dateHourCountMap = new HashMap<String,Map<String,Long>>();
        for (Map.Entry<String, Long> countEntry : countMap.entrySet()){
            String dateHour = countEntry.getKey();
            String date = dateHour.split("_")[0];
            String hour = dateHour.split("_")[1];
            long count = countEntry.getValue();

            Map<String,Long> hourCountMap = dateHourCountMap.get(date);
            if (hourCountMap ==null){
                hourCountMap = new HashMap<String,Long>();
                dateHourCountMap.put(date,hourCountMap);
            }
            dateHourCountMap.put(date,hourCountMap);
        }

2.总共要抽取100个session,按照天数,进行平分

int extractNumberPerDay = 100 /dateHourCountMap.size();

3.在每天的session中根据每个小时所占比例随机抽取各个时间段抽取这个n个session。

        //<date,<hour,(1,3,4,2103)>>
        Map<String,Map<String, List<Integer>>> dateHourExtractMap =
                new HashMap<String,Map<String,List<Integer>>>();

        Random random = new Random();

        for (Map.Entry<String,Map<String,Long>> dateHourCountEntry : dateHourCountMap.entrySet()){
            String date = dateHourCountEntry.getKey();
            Map<String,Long> hourCountMap = dateHourCountEntry.getValue();

            //计算出每天的session总数
            long sessionCount = 0L;
            for (long hourCount : hourCountMap.values()){
                sessionCount += hourCount;
            }

            Map<String,List<Integer>> hourExtractMap  = dateHourExtractMap.get(date);
            if (hourExtractMap == null){
                hourExtractMap = new HashMap<String,List<Integer>>();
                dateHourExtractMap.put(date,hourExtractMap);
            }

            //遍历每一个小时
            for (Map.Entry<String,Long> hourCountEntry : hourCountMap.entrySet()){
                String hour = hourCountEntry.getKey();
                long count = hourCountEntry.getValue();

                // 计算每个小时的session数量,占据当天总session数量的比例,直接乘以每天要抽取的数量
                // 就可以计算出,当前小时需要抽取的session数量
                int hourExtractNumber = (int)((double)count/(double) sessionCount)*extractNumberPerDay;
                if (hourExtractNumber > count){
                    hourExtractNumber = (int)count;
                }

                //先获取当前小时的存放随机数的list
                List<Integer> extractIndexList = hourExtractMap.get(hour);
                if (extractIndexList == null){
                    extractIndexList = new ArrayList<Integer>();
                    hourExtractMap.put(hour,extractIndexList);
                }

                //生成上面计算出来的数量的随机数
                for (int i = 0; i < hourExtractNumber;i++){
                    int extractIndex = random.nextInt((int)count);
                    while (extractIndexList.contains(extractIndex)){
                        extractIndex = random.nextInt((int)count);
                    }
                    extractIndexList.add(extractIndex);
                }

            }


        }

完整代码

UserVisitSessionAnalyzeSpark.java
   /**
     * 随机抽取session
     * @param sessionid2AggrInfoRDD
     */
    private static void randomExtractSession(
            JavaPairRDD<String, String> sessionid2AggrInfoRDD) {
        // 第一步,计算出每天每小时的session数量,获取<yyyy-MM-dd_HH,sessionid>格式的RDD
        JavaPairRDD<String, String> time2sessionidRDD = sessionid2AggrInfoRDD.mapToPair(

                new PairFunction<Tuple2<String,String>, String, String>() {

                    private static final long serialVersionUID = 1L;

                    @Override
                    public Tuple2<String, String> call(
                            Tuple2<String, String> tuple) throws Exception {
                        String aggrInfo = tuple._2;

                        String startTime = StringUtils.getFieldFromConcatString(
                                aggrInfo, "\\|", Constants.FIELD_START_TIME);
                        String dateHour = DateUtils.getDateHour(startTime);

                        return new Tuple2<String, String>(dateHour, aggrInfo);
                    }

                });



        /**
         * 思考一下:这里我们不要着急写大量的代码,做项目的时候,一定要用脑子多思考
         *
         * 每天每小时的session数量,然后计算出每天每小时的session抽取索引,遍历每天每小时session
         * 首先抽取出的session的聚合数据,写入session_random_extract表
         * 所以第一个RDD的value,应该是session聚合数据
         *
         */

        // 得到每天每小时的session数量
        Map<String, Long> countMap =  time2sessionidRDD.countByKey();

        //第二步,使用按时间比例随机抽取算法,计算出每天每小时需要抽取session的索引

        //将<yyyy-MM-dd_HH,count>格式的map,转换为<yyyy-MM-dd,<HH,count>>
        Map<String,Map<String,Long>> dateHourCountMap = new HashMap<String,Map<String,Long>>();
        for (Map.Entry<String, Long> countEntry : countMap.entrySet()){
            String dateHour = countEntry.getKey();
            String date = dateHour.split("_")[0];
            String hour = dateHour.split("_")[1];
            long count = countEntry.getValue();

            Map<String,Long> hourCountMap = dateHourCountMap.get(date);
            if (hourCountMap ==null){
                hourCountMap = new HashMap<String,Long>();
                dateHourCountMap.put(date,hourCountMap);
            }
            dateHourCountMap.put(date,hourCountMap);
        }



        //开始实现按时间比例随机抽取算法

        //总共要抽取100个session,按照天数,进行平分
        int extractNumberPerDay = 100 /dateHourCountMap.size();

        //<date,<hour,(1,3,4,2103)>>
        Map<String,Map<String, List<Integer>>> dateHourExtractMap =
                new HashMap<String,Map<String,List<Integer>>>();

        Random random = new Random();

        for (Map.Entry<String,Map<String,Long>> dateHourCountEntry : dateHourCountMap.entrySet()){
            String date = dateHourCountEntry.getKey();
            Map<String,Long> hourCountMap = dateHourCountEntry.getValue();

            //计算出每天的session总数
            long sessionCount = 0L;
            for (long hourCount : hourCountMap.values()){
                sessionCount += hourCount;
            }

            Map<String,List<Integer>> hourExtractMap  = dateHourExtractMap.get(date);
            if (hourExtractMap == null){
                hourExtractMap = new HashMap<String,List<Integer>>();
                dateHourExtractMap.put(date,hourExtractMap);
            }

            //遍历每一个小时
            for (Map.Entry<String,Long> hourCountEntry : hourCountMap.entrySet()){
                String hour = hourCountEntry.getKey();
                long count = hourCountEntry.getValue();

                // 计算每个小时的session数量,占据当天总session数量的比例,直接乘以每天要抽取的数量
                // 就可以计算出,当前小时需要抽取的session数量
                int hourExtractNumber = (int)((double)count/(double) sessionCount)*extractNumberPerDay;
                if (hourExtractNumber > count){
                    hourExtractNumber = (int)count;
                }

                //先获取当前小时的存放随机数的list
                List<Integer> extractIndexList = hourExtractMap.get(hour);
                if (extractIndexList == null){
                    extractIndexList = new ArrayList<Integer>();
                    hourExtractMap.put(hour,extractIndexList);
                }

                //生成上面计算出来的数量的随机数
                for (int i = 0; i < hourExtractNumber;i++){
                    int extractIndex = random.nextInt((int)count);
                    while (extractIndexList.contains(extractIndex)){
                        extractIndex = random.nextInt((int)count);
                    }
                    extractIndexList.add(extractIndex);
                }

            }


        }

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值