spark scala-distinct使用

本文主要通过使用spark的distinct进行去重,实现简单的UV统计

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.types.IntegerType
import org.apache.spark.sql.functions._

/**
 * @author jhp
  *         spark 使用distinct去重
 */
object DailyUV {
  
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
        .setMaster("local")  
        .setAppName("DailyUV")
    val sc = new SparkContext(conf)
    val sqlContext = new SQLContext(sc)
    
    // 这里着重说明一下!!!
    // 要使用Spark SQL的内置函数,就必须在这里导入SQLContext下的隐式转换
    import sqlContext.implicits._
    
    // 构造用户访问日志数据,并创建DataFrame
    
    // 模拟用户访问日志,日志用逗号隔开,第一列是日期,第二列是用户id
    val userAccessLog = Array(
        "2015-10-01,1122",
        "2015-10-01,1122",
        "2015-10-01,1123",
        "2015-10-01,1124",
        "2015-10-01,1124",
        "2015-10-02,1122",
        "2015-10-02,1121",
        "2015-10-02,1123",
        "2015-10-02,1123");
    val userAccessLogRDD = sc.parallelize(userAccessLog, 5)
    
    // 将模拟出来的用户访问日志RDD,转换为DataFrame
    // 首先,将普通的RDD,转换为元素为RowRDD
    val userAccessLogRowRDD = userAccessLogRDD
        .map { log => Row(log.split(",")(0), log.split(",")(1).toInt) }
    // 构造DataFrame的元数据
    val structType = StructType(Array(
        StructField("date", StringType, true),
        StructField("userid", IntegerType, true)))  
    // 使用SQLContext创建DataFrame
    val userAccessLogRowDF = sqlContext.createDataFrame(userAccessLogRowRDD, structType)  
    
    // 这里讲解一下uv的基本含义和业务
    // 每天都有很多用户来访问,但是每个用户可能每天都会访问很多次
    // 所以,uv,指的是,对用户进行去重以后的访问总数
    
    // 这里,正式开始使用Spark 1.5.x版本提供的最新特性,内置函数,countDistinct
    // 讲解一下聚合函数的用法
    // 首先,对DataFrame调用groupBy()方法,对某一列进行分组
    // 然后,调用agg()方法 ,第一个参数,必须,必须,传入之前在groupBy()方法中出现的字段
    // 第二个参数,传入countDistinctsumfirst等,Spark提供的内置函数
    // 内置函数中,传入的参数,也是用单引号作为前缀的,其他的字段
    userAccessLogRowDF.groupBy("date")
        .agg('date, countDistinct('userid))  
        .map { row => Row(row(1), row(2)) }   
        .collect()
        .foreach(println)  
  }
  
}

猜你喜欢

转载自blog.csdn.net/qq_18603599/article/details/79969902