Spark Graphx:从邻接矩阵加载图形

时间:2016-12-18 06:17:57

标签: scala apache-spark apache-spark-sql spark-graphx

我一直在尝试使用Spark的Graphx API,主要是为了学习并了解如何使用它们。在这个过程中,我必须将邻接矩阵加载到图形中。矩阵数据集为here

从网站上,矩阵被描述为

  

一家工厂的一些员工接受了一个问题的采访:“你喜欢和你的同事一起工作吗?”可能的答案是1表示是,0表示否。每位员工都为每位员工提供了答案,从而创建了一个adjecancy矩阵。

所以,我决定将员工命名为英文字母(" A"以后)。员工构成图表的节点,他们对同事的偏好构成了边缘。我没有在Spark中找到任何直接的方法来实现这一目标;我的R程序员朋友告诉我,在他们的世界中这样做很容易。所以,我开始写一个天真的实现来做到这一点。这是代码

val conf = new SparkConf().setMaster("local[*]").setAppName("GraphExploration App")
val spark = SparkSession
  .builder()
  .appName("Spark SQL: beginners exercise")
  .getOrCreate()     

    val sc = SparkContext.getOrCreate(conf)

      val df = spark.read.csv("./BlogInputs/sociogram-employees-un.csv").cache

      val allRows = df.toLocalIterator.toIndexedSeq

      type EmployeeVertex = (Long,String)

      val employeesWithNames = (0 until allRows.length).map(i => (i.toLong,((i + 'A').toChar.toString())))

      val columnNames   = (0 until allRows.length).map(i => ("_c" + i)).toIndexedSeq // It is a square matrix; rows == columns

      val edgesAsCollected = (for {
            rowIndex <- 0 until df.count.toInt
            colIndex <- 0 until df.count.toInt
            if (rowIndex != colIndex)
            } yield {

                    if (allRows(rowIndex).fieldIndex(columnNames(colIndex)) == 1)
                        Some(Edge(employeesWithNames(rowIndex)._1,employeesWithNames(colIndex)._1,"Likes"))
                    else
                       None

            }).flatten

       val employeeNodes = sc.parallelize(employeesWithNames)
       val edges = sc.parallelize(edgesAsCollected)

       val employeeGraph = Graph(sc.parallelize(employeesWithNames),edges,"Nobody")

这是架构:

scala>df.printSchema
root
 |-- _c0: string (nullable = true)
 |-- _c1: string (nullable = true)
 |-- _c2: string (nullable = true)
 |-- _c3: string (nullable = true)
 |-- _c4: string (nullable = true)
 |-- _c5: string (nullable = true)
 |-- _c6: string (nullable = true)
 |-- _c7: string (nullable = true)
 |-- _c8: string (nullable = true)
 |-- _c9: string (nullable = true)
 |-- _c10: string (nullable = true)
 |-- _c11: string (nullable = true)
 |-- _c12: string (nullable = true)
 |-- _c13: string (nullable = true)
 |-- _c14: string (nullable = true)
 |-- _c15: string (nullable = true)
 |-- _c16: string (nullable = true)
 |-- _c17: string (nullable = true)
 |-- _c18: string (nullable = true)
 |-- _c19: string (nullable = true)
 |-- _c20: string (nullable = true)
 |-- _c21: string (nullable = true)
 |-- _c22: string (nullable = true)
 |-- _c23: string (nullable = true)
 |-- _c24: string (nullable = true)

..和前几行

scala> df.show
16/12/21 07:12:00 WARN Executor: 1 block locks were not released by TID = 1:
[rdd_8_0]
+---+---+---+---+---+---+---+---+---+---+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|_c0|_c1|_c2|_c3|_c4|_c5|_c6|_c7|_c8|_c9|_c10|_c11|_c12|_c13|_c14|_c15|_c16|_c17|_c18|_c19|_c20|_c21|_c22|_c23|_c24|
+---+---+---+---+---+---+---+---+---+---+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|  0|  1|  0|  1|  1|  0|  1|  1|  1|  0|   0|   1|   0|   1|   1|   0|   1|   1|   0|   1|   0|   1|   0|   1|   1|
|  1|  0|  0|  1|  0|  0|  1|  0|  1|  0|   0|   1|   0|   0|   1|   0|   1|   0|   1|   0|   0|   1|   0|   1|   0|
|  0|  1|  0|  1|  1|  0|  0|  0|  1|  0|   0|   0|   0|   1|   1|   0|   0|   1|   0|   0|   0|   1|   1|   0|   1|
|  0|  1|  1|  0|  0|  0|  1|  0|  0|  0|   1|   1|   0|   1|   0|   0|   1|   1|   0|   0|   1|   0|   1|   1|   0|

这符合我的目的,但我觉得可能有不同的方式。我对Spark的MLLib API知之甚少可能是一个障碍。有人可以对此发表评论吗?甚至更好,有人可以告诉我一个更好但更简单的方法(通过编辑我的代码,如果有必要)?

1 个答案:

答案 0 :(得分:1)

对于手头的案例,我发现@ DanieldePaula的建议可以接受:

  

由于矩阵是方形的,非常多的行意味着大量的列,在这种情况下,使用SparkSQL在我看来似乎并不是最优的。如果将矩阵转换为稀疏格式,例如,我认为你可以使用Spark来解决这个问题。 RDD [(row,col,value)],那么创建顶点和边缘将非常容易。

谢谢,丹尼尔!