• spark影评


    package movierating

    import org.apache.spark.SparkConf
    import org.apache.spark.rdd.RDD
    import org.apache.spark.sql.{Row, SparkSession}
    import org.apache.spark.sql.types.{DoubleType, StringType, StructField, StructType}

    object MovieRating {
    def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("RDD_MOVIE_USERS_ANALYZER")

    val spark = SparkSession.builder().config(conf).getOrCreate()

    val sc = spark.sparkContext

    //设置日志级别
    sc.setLogLevel("WARN")

    //读取数据
    val dataPath = "E:\sparkproject\src\main\data\"
    val usersRDD = sc.textFile(dataPath + "users.dat")
    val moviesRDD = sc.textFile(dataPath + "movies.dat")
    val ratingsRDD = sc.textFile(dataPath + "ratings.dat")


    /*具体业务处理逻辑*/
    val movieAndRatingArray = getTop10TitleAndAvgRating(spark, moviesRDD, ratingsRDD)
    for ((movie, rating) <- movieAndRatingArray) {
    println(movie + "评分为:" + rating)
    }

    val movieAndRatingArrayForGender = getFemailTop10TitleAndAvgRating(spark, moviesRDD, ratingsRDD, usersRDD, "M")
    for ((movie, rating) <- movieAndRatingArrayForGender) {
    println(movie + "评分为:" + rating)
    }

    val sortedResult = sortByTimeAndRating(moviesRDD, ratingsRDD)
    for (movie <- sortedResult) {
    println(movie)
    }

    CntGroupByGenderAndAgeWithDF(spark, usersRDD, ratingsRDD, moviesRDD)

    CntGroupByGenderAndAgeWithDS(spark, usersRDD, ratingsRDD, moviesRDD)
    //关闭SparkSession
    spark.close()

    }

    /**
    * 获取top10电影及平均分
    *
    * @param spark
    * @param moviesRDD
    * @param ratingsRDD
    * @return
    */
    def getTop10TitleAndAvgRating(spark: SparkSession, moviesRDD: RDD[String], ratingsRDD: RDD[String]): Array[(String, Double)] = {
    //(movie_id,title)
    val movieInfo = moviesRDD.map(_.split("::")).map(x => (x(0), x(1))).cache()
    //(user_id,movie_id,rating)
    val ratings = ratingsRDD.map(_.split("::")).map(x => (x(0), x(1), x(2))).cache()
    //(movie_id,(sum(rating),count(1)))
    val movieAndRatings = ratings.map(x => (x._2, (x._3.toDouble, 1))).reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))
    //(movie_id,avg)
    val avgRatings = movieAndRatings.map(x => (x._1, x._2._1.toDouble / x._2._2))
    //sort
    val titleAndAvg = avgRatings.join(movieInfo).map(x => (x._2._1, x._2._2)).sortByKey(false).map(x => (x._2, x._1)).take(10)
    titleAndAvg
    }


    /**
    * 获取性别电影偏好
    *
    * @param spark
    * @param moviesRDD
    * @param ratingsRDD
    * @param usersRDD
    * @param gender
    * @return
    */
    def getFemailTop10TitleAndAvgRating(spark: SparkSession, moviesRDD: RDD[String], ratingsRDD: RDD[String], usersRDD: RDD[String], gender: String): Array[(String, Double)] = {
    //user_id
    val userGender = usersRDD.map(_.split("::")).map(x => (x(0), x(1))).filter(x => x._2.equals(gender)).cache()
    //(movie_id,title)
    val movieInfo = moviesRDD.map(_.split("::")).map(x => (x(0), x(1))).cache()
    //(user_id,(movie_id,rating))
    val ratings: RDD[(String, (String, String))] = ratingsRDD.map(_.split("::")).map(x => (x(0), (x(1), x(2)))).cache()
    //(movie_id,rating)
    val FemailUserRating = userGender.join(ratings).map(x => (x._2._2._1, x._2._2._2))
    //(movie_id,(sum(rating),count(1)))
    val FemailMovieAndRating = FemailUserRating.map(x => (x._1, (x._2.toDouble, 1))).reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))
    //(movie_id,avg)
    val femailMovieAndAvgRating = FemailMovieAndRating.map(x => (x._1, x._2._1.toDouble / x._2._2))
    val titleAndAvg = femailMovieAndAvgRating.join(movieInfo).map(x => (x._2._1, x._2._2)).sortByKey(false).map(x => (x._2, x._1)).take(10)
    titleAndAvg
    }

    /**
    * 通过时间戳与评分进行二次排序
    *
    * @param moviesRDD
    * @param ratingsRDD
    * @return
    */
    def sortByTimeAndRating(moviesRDD: RDD[String], ratingsRDD: RDD[String]): Array[String] = {


    val movieInfo = moviesRDD.map(_.split("::")).map(x => (x(0), x(1))).cache()
    val pairWithSortKey = ratingsRDD.map(line => {
    val splited = line.split("::")
    (new SecondarySortKey(splited(3).toDouble, splited(2).toDouble), splited(1))
    })

    pairWithSortKey.sortByKey(false).map(x => (x._2, x._1)).join(movieInfo).map(x => x._2._2).take(10)
    }

    /**
    * DF
    *
    * @param spark
    * @param usersRDD
    * @param ratingsRDD
    * @param moviesRDD
    */
    def CntGroupByGenderAndAgeWithDF(spark: SparkSession, usersRDD: RDD[String], ratingsRDD: RDD[String], moviesRDD: RDD[String]): Unit = {
    val schemaForUsers = StructType("UserID::Gender::Age::OccupationID::Zip-code".split("::").map(column => StructField(column, StringType, true)))
    val usersRDDRows = usersRDD.map(_.split("::")).map(line => Row(line(0).trim, line(1).trim, line(2).trim, line(3).trim, line(4).trim))
    val usersDataFrame = spark.createDataFrame(usersRDDRows, schemaForUsers)
    val schemaforratings = StructType("UserID::MovieID".split("::").map(column => StructField(column, StringType, true)))
    .add("Rating", DoubleType, true)
    .add("Timestamp", StringType, true)

    val ratingsRDDRows = ratingsRDD.map(_.split("::")).map(line => Row(line(0).trim, line(1).trim, line(2).trim.toDouble, line(3).trim))
    val ratingsDataFrame = spark.createDataFrame(ratingsRDDRows, schemaforratings)
    val schemaformovies = StructType("MovieID::Title::Genres".split("::").map(column => StructField(column, StringType, true)))
    val moviesRDDRows = moviesRDD.map(_.split("::")).map(line => Row(line(0).trim, line(1).trim, line(2).trim))
    val moviesDataFrame = spark.createDataFrame(moviesRDDRows, schemaformovies)
    ratingsDataFrame.filter(s"MovieID=1193").join(usersDataFrame, "UserID")
    .select("Gender", "Age")
    .groupBy("Gender", "Age")
    .count().show(10)

    //会话级别
    ratingsDataFrame.createTempView("ratings")
    usersDataFrame.createTempView("users")
    val sql_local = "select gender,age,count(*) from users u join ratings r on u.userid = r.userid where movieid =1193 group by gender,age"
    spark.sql(sql_local).show()
    //application级别,global_temp
    ratingsDataFrame.createGlobalTempView("ratings")
    usersDataFrame.createGlobalTempView("users")
    val sql = "select gender,age,count(*) from global_temp.users u join global_temp.ratings r on u.userid = r.userid where movieid =1193 group by gender,age"
    spark.sql(sql).show()
    //隐式转换
    import spark.sqlContext.implicits._
    ratingsDataFrame.select("movieid", "rating")
    .groupBy("movieid").avg("rating")
    .rdd.map(row => (row(1), (row(0), row(1))))
    .sortBy(_._1.toString.toDouble, false)
    .map(x => x._2).collect.take(10).foreach(println)
    }


    /**
    * DS
    *
    * @param userID
    * @param gender
    * @param Age
    * @param OccupationID
    * @param Zip_Code
    */
    case class User(userID: String, gender: String, Age: String, OccupationID: String, Zip_Code: String)

    case class Rating(userID: String, movieID: String, rating: Double, Timestamp: String)

    def CntGroupByGenderAndAgeWithDS(spark: SparkSession, usersRDD: RDD[String], ratingsRDD: RDD[String], moviesRDD: RDD[String]): Unit = {

    import spark.implicits._
    val usersForDSRDD = usersRDD.map(_.split("::")).map(x => User(x(0).trim, x(1).trim, x(2).trim, x(3).trim, x(4).trim))
    val userDataSet = spark.createDataset[User](usersForDSRDD)
    userDataSet.show()

    val ratingsForDSRDD = ratingsRDD.map(_.split("::")).map(x => Rating(x(0).trim, x(1).trim, x(2).trim.toDouble, x(3).trim))
    val ratingDataSet = spark.createDataset[Rating](ratingsForDSRDD)
    ratingDataSet.filter(s"movieid=1193").join(userDataSet, "userid").select("gender", "age")
    .groupBy("gender", "age").count().orderBy($"gender".desc, $"age").show()
    }
    }




    package movierating

    /**
    * 实现二次排序
    *
    * @param first
    * @param second
    */
    class SecondarySortKey(val first: Double, val second: Double) extends Ordered[SecondarySortKey] with Serializable {
    override def compare(that: SecondarySortKey): Int = {
    //先比较第一个是否相等
    if (this.first - that.first != 0) {
    (this.first - that.first).toInt
    } else {
    if (this.second - that.second > 0) {
    Math.ceil(this.second - that.second).toInt
    } else if (this.second - that.second < 0) {
    Math.floor(this.second - that.second).toInt
    } else {
    (this.second - that.second).toInt
    }
    }
    }
    }
  • 相关阅读:
    PHP __autoload()方法真的影响性能吗?
    MYSQL 逻辑架构
    Ajax.dll的初探
    教育技术反思
    祝天下所有的老师教师节快乐
    Asp.net+Xml+js实现无线级下拉菜单
    有调查就有发言权
    控件事件神奇实效
    Inspiration 7.6使用时出现的问题
    最常用的加密类
  • 原文地址:https://www.cnblogs.com/yin-fei/p/12047441.html
Copyright © 2020-2023  润新知