zoukankan      html  css  js  c++  java
  • spark之手机基站定位数据的商圈分析

    一.目的

    基于基站定位数据的商圈分析
    移动通信网络会记录用户手机的相关信息,比如手机所处的基站区域编号,所处基站的时间等。根据这些数据可以进行商圈划分,目的是
    为了研究潜在的顾客的分布以制定适宜的商业对策。如:可划分商业区、住宅区以及工作区

    二.数据

    数据来源【Python数据分析与挖掘实战(第14章基于基站定位数据的商圈分析)】,可自行搜索下载。

    原始数据集没有找到,找到的数据是被统计,转换,过滤过的数据:
    这四个特征的统计方法是:
    对于某个基站(观测窗口为L天,基站N个,用户M个;
    某个用户i在j天在某个基站的 =》 工作日上班时间停留时间为weekday,凌晨停留时间为night,周末停留时间weekend,是否停留为stay【1:停留;0:无停留】):

    工作日上班时间人均停留时间(9:00-18:00)
    凌晨人均停留时间(00:00-07:00)
    周末人均停留时间
    日均人流量

    基站编号,工作日上班时间人均停留时间,凌晨人均停留时间,周末人均停留时间,日均人流量
      36902,  78,                     521,           602,           2863
      36903,  144,                    600,           521,           2245
      36904,  95,                     457,           468,           1283
      36905,  69,                     596,           695,           1054

    三.代码

    通过提取和处理特征,利用聚类方法聚成几个区域,并对区域进行分析。详细代码:手机基站定位数据的商圈分析(https://github.com/jiangnanboy/spark_tutorial)

    public static void businessCircleStatistics(SparkSession session) {
            String path = PropertiesReader.get("intermediate_business_circle_csv");
            /**
             * +--------+--------------------------+----------------+----------------+----------+
             * |基站编号 |工作日上班时间人均停留时间   |凌晨人均停留时间  |周末人均停留时间  |日均人流量|
             * +--------+--------------------------+----------------+----------------+----------+
             * |   36902|                        78|             521|             602|      2863|
             * |   36903|                       144|             600|             521|      2245|
             * |   36904|                        95|             457|             468|      1283|
             * |   36905|                        69|             596|             695|      1054|
             * |   36906|                       190|             527|             691|      2051|
             * +--------+--------------------------+----------------+----------------+----------+
             *  |-- 基站编号: integer (nullable = true)
             *  |-- 工作日上班时间人均停留时间: integer (nullable = true)
             *  |-- 凌晨人均停留时间: integer (nullable = true)
             *  |-- 周末人均停留时间: integer (nullable = true)
             *  |-- 日均人流量: integer (nullable = true)
             */
            Dataset<Row> dataset = session.read()
                    .option("sep", ",")
                    .option("header", "true")
                    .option("inferSchema", "true")
                    .csv(path);
    
            /**
             * 转为特征向量
             * +---------+--------------------+
             * |stationID|            features|
             * +---------+--------------------+
             * |    36902|[78.0,521.0,602.0...|
             * |    36903|[144.0,600.0,521....|
             * |    36904|[95.0,457.0,468.0...|
             * |    36905|[69.0,596.0,695.0...|
             * |    36906|[190.0,527.0,691....|
             * +---------+--------------------+
             */
            dataset = dataset.map((MapFunction<Row,Row>) row -> {
                int stationID = row.getInt(0);
                double weekdayAvg = (double) row.getInt(1);
                double nightAvg = (double) row.getInt(2);
                double weekendAvg = (double) row.getInt(3);
                double stayAvg = (double) row.getInt(4);
                return RowFactory.create(stationID, Vectors.dense(new double[]{weekdayAvg, nightAvg, weekendAvg, stayAvg}));
            }, RowEncoder.apply(new StructType(new StructField[]{
                    new StructField("stationID", DataTypes.IntegerType,false, Metadata.empty()),
                    new StructField("features", SQLDataTypes.VectorType(), false, Metadata.empty())
            })));
    
            /**
             * 数据标准化
             */
            MinMaxScalerModel featureScaler = new MinMaxScaler()
                    .setInputCol("features")
                    .setOutputCol("scaledFeatures")
                    .fit(dataset);
            /**
             *+---------+--------------------+--------------------+
             * |stationID|            features|      scaledFeatures|
             * +---------+--------------------+--------------------+
             * |    36902|[78.0,521.0,602.0...|[0.10386473429951...|
             * |    36903|[144.0,600.0,521....|[0.26328502415458...|
             * |    36904|[95.0,457.0,468.0...|[0.14492753623188...|
             * |    36905|[69.0,596.0,695.0...|[0.08212560386473...|
             * |    36906|[190.0,527.0,691....|[0.37439613526570...|
             * +---------+--------------------+--------------------+
             */
            Dataset<Row> scaledData = featureScaler.transform(dataset);
    
            /**
             * 轮廓系统确定簇数,可以看出分为3类最佳
             * k: 2 silhouette: 0.5063659448997802
             * k: 3 silhouette: 0.629019144457301
             * k: 4 silhouette: 0.32319167016337247
             * k: 5 silhouette: 0.30681655682008674
             * k: 6 silhouette: 0.39947777279975305
             * k: 7 silhouette: 0.31054738863541337
             * k: 8 silhouette: 0.3417574406084828
             * k: 9 silhouette: 0.30133745097199804
             * k: 10 silhouette: 0.12586962519806658
             */
            int k = selectOptimalK(scaledData, 10);
    
            //model,利用层次聚类
            BisectingKMeans bkm = new BisectingKMeans().setFeaturesCol("scaledFeatures")
                    .setK(k) //簇数
                    .setSeed(1);
            BisectingKMeansModel model = bkm.fit(scaledData);
            /**
             * 预测结果,后面根据聚类结果划分出不同的商圈,对3类数据中的4个特征进行分析,定义3类商圈的不定定位进行商业活动,具体可看《python数据分析与挖掘实战》一书中的第14章。
             * 根据3类数据的活动并异,可划分商业区、住宅区以及工作区
             * +---------+--------------------+--------------------+----------+
             * |stationID|            features|      scaledFeatures|prediction|
             * +---------+--------------------+--------------------+----------+
             * |    36902|[78.0,521.0,602.0...|[0.10386473429951...|         1|
             * |    36903|[144.0,600.0,521....|[0.26328502415458...|         1|
             * |    36904|[95.0,457.0,468.0...|[0.14492753623188...|         1|
             * |    36905|[69.0,596.0,695.0...|[0.08212560386473...|         1|
             * |    36906|[190.0,527.0,691....|[0.37439613526570...|         1|
             * +---------+--------------------+--------------------+----------+
             */
    
            Dataset<Row> predictions  = model.transform(scaledData);
            predictions.show(5);
    
            /**
             * 聚类中心
             * [0.13227119317053798,0.04483188044831879,0.19956941131772793,0.7100471677339725]
             * [0.1886016451233843,0.8021375921375923,0.7629929621455044,0.09096028267984407]
             * [0.8643640466871185,0.048015925680159235,0.12134333562021299,0.3287583779747489]
             */
    
            Vector[] centers = model.clusterCenters();
            for(Vector center : centers) {
                System.out.println(center);
            }
    
        }
  • 相关阅读:
    数据库mysql基础语言--各模式的含义
    Linux下判断磁盘是SSD还是HDD的几种方法
    linux解压大全
    RedHat Linux RHEL6配置本地YUM源
    利用ssh传输文件-服务器之间传输文件
    深入理解asp.net里的HttpModule机制
    WPF(一)
    JS中caller和callee
    Vue-Methods中使用Filter
    c#值类型与引用类型区别
  • 原文地址:https://www.cnblogs.com/little-horse/p/14018503.html
Copyright © 2011-2022 走看看