SparkInAction 图计算 用户关系染色分析
前言
需求:如果一个用户使用了某个手机,这个手机上登录过其他的用户,那么这些用户是有关系的,同样用户关联到的用户又可以通过手机关联到其他用户 这样就构成了一个强大的关系网。现在给出用户与手机登录关系表,请找出所有的用户是有关系的。
问题分析
整个用户手机关系网拓扑图如下图所示:
从图中可以发现,找到有关系的关联的用户,就是要找出上面无向图的所有联通分支。比如上图有两个联通分支。
测试数据集
对应上图,测试数据集合如下:
#user_id,phone_id
001,01
002,01
003,01
004,01
005,01
004,02
006,02
007,02
008,02
009,03
010,03
011,03
希望的输出结果为所有关联的用户对应同一个ID。
测试代码
val rootDir = "datas"
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("SparkInAction").setMaster("local")
val sc = new SparkContext(conf)
val userPhoneRS = sc.textFile(rootDir + "/user_phone.relationship")
# 生成用户对应的点
val users: RDD[(VertexId, (String))] =
userPhoneRS.map(_.split(",")(0)).distinct()
.map(userId => (userId.toLong, ("TEST_USER")))
# 生成手机对应的点,为了防止手机ID和用户ID重复,使用了一个小技巧,就是手机ID = 最大的用户ID + 手机ID
val maxUserId = users.max()._1
val phones: RDD[(VertexId, (String))] =
userPhoneRS.map(_.split(",")(1)).distinct()
.map(phoneId => (phoneId.toLong + maxUserId, ("TEST_PHONE")))
# 生成所有的点
val vertices = users.union(phones)
# 生成所有的边
val edges: RDD[Edge[String]]= userPhoneRS.map {
line =>
val up = line.split(",")
Edge(up(0).toLong, up(1).toLong + maxUserId, "TEST_EDGE")
}
# 生成图
val default = ("Missing")
val graph = Graph(vertices, edges, default)
graph.vertices.collect().foreach(println)
graph.edges.collect().foreach(println)
# 找到所有的联通分支
val graph2 = graph.connectedComponents()
# 结果展示
graph2.vertices.filter(_._1 <= maxUserId).collect().foreach(println)
}
运行结果:
(4,1)
(6,1)
(8,1)
(10,9)
(2,1)
(11,9)
(1,1)
(3,1)
(7,1)
(9,9)
(5,1)
可以发现,结果正如我们所料。
总结
基于 Spark GraphX 可以做很多图计算方面的事情,而且是分布式,速度比单机处理快,值得好好研究。 下面推荐一下好的资料:
- Spark官网永远是最好的资料
- Spark中文快速上手
个人微信公众号
欢迎关注本人微信公众号,会定时发送关于大数据、机器学习、Java、Linux 等技术的学习文章,而且是一个系列一个系列的发布,无任何广告,纯属个人兴趣。