版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012848709/article/details/85647697
楔子
学习《spark大数据商业实战》第12章节,统计所有电影平均得分最高的前10部电影
数据说明
详细github代码
1:用户文件users.dat---------------------------------------
UserID::Gender::Age::OccupationID::Zip-code
用户id 性别M是男性 年龄 职业 邮编
2:ratings.dat---------------------------------------------
UserID::MovieID::Rating::Timestamp
用户ID 电影id评分数据 时间戳
----------------------------------------------------------
3:movies.dat
MovieID::Title::Genres
电影ID 电影名 电影类型
4:职业Occupation.dat--------------------------------------
OccupationID::OccupationName
职业id 职业
推荐系统常用数据集
https://www.cnblogs.com/shenxiaolin/p/8337913.html
思路
分为3步骤:
- 把数据变为key-value ,eg (MovieID,(Rating,1))
- 通过reduceByKey 汇总,key是MovieID,但是values是(评分总和,点评人数合计) (此处是之前不曾遇到的思路)
- sortByKey(false) 倒序排列,在通过take取出前10位
demo
RDD方式
/**
* 1:RDD实现电影流行度 (1):所有电影中平均得分最高的Top10电影
*
*/
private static void rddForMovieTop10(JavaRDD<String> ratRdd) {
// step 1 把数据变为key-value ,eg (MovieID,(Rating,1))
JavaPairRDD<String, Tuple2<Long, Long>> mapToPair = ratRdd.mapToPair(new PairFunction<String, String, Tuple2<Long, Long>>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Tuple2<Long, Long>> call(String t) throws Exception {
String[] split = t.split("::");// UserID::MovieID::Rating::Timestamp
Tuple2<Long, Long> tuple2 = new Tuple2<Long, Long>(Long.valueOf(split[2]), 1L);
return new Tuple2<String, Tuple2<Long, Long>>(split[1], tuple2);
}
});
// step 2 通过reduceByKey 汇总,key是MovieID,但是values是(评分总和,点评人数合计)
JavaPairRDD<String, Tuple2<Long, Long>> reduceByKey = mapToPair.reduceByKey(new Function2<Tuple2<Long, Long>, Tuple2<Long, Long>, Tuple2<Long, Long>>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<Long, Long> call(Tuple2<Long, Long> v1, Tuple2<Long, Long> v2) throws Exception {
return new Tuple2<Long, Long>(v1._1 + v2._1, v1._2 + v2._2);
}
});
// step 3 sortByKey(false) 倒序排列
JavaPairRDD<Double, String> result = reduceByKey.mapToPair(new PairFunction<Tuple2<String, Tuple2<Long, Long>>, Double, String>() {
@Override
public Tuple2<Double, String> call(Tuple2<String, Tuple2<Long, Long>> v1) throws Exception {
// TODO 都是整数 做除法还是整数
double avg = v1._2._1 * 0.1 / v1._2._2;
return new Tuple2<Double, String>(avg, v1._1);
}
});
System.out.println("所有电影中平均得分最高的Top10电影 RDD方式");
result.sortByKey(false).take(10).forEach(t -> System.out.println(t));
}
SparkSQL方式
/**
* 1:RDD实现电影流行度 (1):所有电影中平均得分最高的Top10电影Bysql
*
*/
private static void rddForMovieTop10Bysql(Dataset<Row> ratDF) {
ratDF.createOrReplaceTempView("t_rat");
Dataset<Row> sql = sparkSession.sql("select * from ("//
+ "select avg(rat) rat_avg ,MovieID from t_rat group by MovieID order by rat_avg desc" //
+ " ) limit 20");
System.out.println("所有电影中平均得分最高的Top20电影 SQL方式");
sql.show();
}
结果如下