Spark RDD求TopN案例

需求

  • 求每个省份广告点击次数top3

数据

数据说明:时间戳,省份,城市,用户,广告。

1516609143867 6 7 64 16
1516609143869 9 4 75 18
1516609143869 1 7 87 12
1516609143869 2 8 92 9
1516609143869 6 7 84 24
1516609143869 1 8 95 5
1516609143869 8 1 90 29
1516609143869 3 3 36 16
1516609143869 3 3 54 22
1516609143869 7 6 33 5
1516609143869 8 2 91 27
1516609143869 0 5 66 5
1516609143869 1 3 33 6
1516609143869 6 2 97 21
1516609143869 5 2 95 24
1516609143869 8 9 73 11
1516609143869 4 8 62 15
1516609143869 5 5 40 23
1516609143869 6 6 53 17

思路分析

  • map映射,取出省份id和广告id,并组成数据结构(省份-广告,1)的形式。
  • 按照key进行聚合,统计广告点击次数,(省份-广告,count)。
  • map映射,切分省份和广告,并组成数据结构(省份,(广告,count))的形式。
  • 按照省份分组。
  • 组内按照count倒序排序取前三。

代码实现

    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    // 加载数据
    val data: RDD[String] = sc.textFile("agent.log")
    // map映射,切分数据,组成(省份-广告,1)的格式
    val proAndAd_1: RDD[(String, Int)] = data.map {
      line => {
        val dataSplit: Array[String] = line.split(" ")
        val proAndAd: String = dataSplit(1) + "-" + dataSplit(4)
        (proAndAd, 1)
      }
    }
    // 按照key聚合数据 (省份-广告,count)
    val proAndAdCount: RDD[(String, Int)] = proAndAd_1.reduceByKey(_ + _)
    // map映射,切分key,并返回数据格式(省份,(广告,count))
    val proKeyAndAdCount: RDD[(String, (String, Int))] = proAndAdCount.map {
      // 模式匹配
      case (proAndAd, count) => {
        val proAndAdSplit: Array[String] = proAndAd.split("-")
        (proAndAdSplit(0), (proAndAdSplit(1), count))
      }
    }
    // 按照key分组
    val groupProAndAdCount: RDD[(String, Iterable[(String, Int)])] = proKeyAndAdCount.groupByKey()
    // 同一组内按照count排序并取前三
    val resRDD: RDD[List[(String, Int)]] = groupProAndAdCount.map {
      case (province, adCount) => {
        adCount.toList.sortWith(_._2 > _._2).take(3)
      }
    }

    resRDD.collect().foreach(println)
    sc.stop()

你可能感兴趣的:(spark,spark,TopN)