如何使用Spark Scala中的Graph.fromEdgeTuples从CSV文件创建图表

时间:2015-09-04 11:00:59

标签: scala csv apache-spark rdd spark-graphx

我是SparkScala的新手,我正在尝试执行一项简单的任务,即根据文本文件中的数据创建图表。

来自文档

  

https://spark.apache.org/docs/0.9.0/api/graphx/index.html#org.apache.spark.graphx.Graph $ @ fromEdges [VD,ED]%28RDD [Edge [ED]],VD%29%28ClassTag [VD],ClassTag [ED]%29:图形[VD,ED]

我可以看到我可以从tuples of vertices创建图表。

我的简单文本文件如下所示,其中每个数字都是一个顶点:

v1 v3
v2 v1
v3 v4
v4
v5 v3

当我从文件中读取数据时

  

val myVertices = myData.map(line => line.split(""))   我得到一个RDD [Array [String]]。

我的问题是:

  1. 如果这是解决问题的正确方法,请如何将RDD[Array[String]]转换为正确的格式,根据文档RDD[(VertexId, VertexId)]VertexID必须是类型长,我正在使用字符串)

  2. 我是否有另一种更简单的方法可以从类似的csv文件结构构建图形?

  3. 任何建议都会非常受欢迎。谢谢!

4 个答案:

答案 0 :(得分:3)

您可以通过多种方式从文本文件创建图表。

此代码根据 Graph.fromEdgeTuples 方法

创建图表
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.graphx.GraphLoader
import scala.util.MurmurHash
import org.apache.spark.graphx.Graph
import org.apache.spark.rdd.RDD
import org.apache.spark.graphx.VertexId

object GraphFromFile {
  def main(args: Array[String]) {

    //create SparkContext
    val sparkConf = new SparkConf().setAppName("GraphFromFile").setMaster("local[*]")
    val sc = new SparkContext(sparkConf)

    // read your file
    /*suppose your data is like 
    v1 v3
    v2 v1
    v3 v4
    v4 v2
    v5 v3
    */
    val file = sc.textFile("src/main/resources/textFile1.csv");

    // create edge RDD of type RDD[(VertexId, VertexId)]
    val edgesRDD: RDD[(VertexId, VertexId)] = file.map(line => line.split(" "))
      .map(line =>
        (MurmurHash.stringHash(line(0).toString), MurmurHash.stringHash(line(1).toString)))

    // create a graph 
    val graph = Graph.fromEdgeTuples(edgesRDD, 1)

    // you can see your graph 
    graph.triplets.collect.foreach(println)

  }
}
使用了

MurmurHash.stringHash ,因为文件包含String形式的顶点。如果它是Numeric类型,则不需要它。

答案 1 :(得分:0)

首先,您应该阅读并理解Spark编程指南:https://spark.apache.org/docs/1.1.0/graphx-programming-guide.html

接下来,您需要确定要在图表中表示的边缘和顶点类型。鉴于您似乎没有任何东西可以附加到您的顶点和边缘,看起来您需要类似的东西:

type MyVertex = (Long,Unit)

如果你发现你确实有一些东西,比如String,要附加到每个顶点,然后用字符串替换Unit,在下面,用适当的String替换null。

现在你需要一个数组(或其他Seq)的顶点然后转换为RDD - 就像这样:

val vertices: Seq[MyVertex] = Array(new MyVertex(1L,null),new MyVertex(2L,null),new MyVertex(3L,null))
val rddVertices: RDD[(VertexId, Unit)] = sc.parallelize(vertices)

其中 sc 是您的SparkContext实例。并且您的顶点和边缘将从CSV文件中读取并适当地转换为long。我不会详细说明该代码,但它很简单,特别是如果您更改CSV文件的格式以删除" v"来自每个顶点id的前缀。

同样,您必须创建所需的边缘:

type MyEdge = Edge[Unit]
val edge1 = new MyEdge(1L,2L)
val edge2 = new MyEdge(2L,3L)
val edges = Array(edge1,edge2)
val rdd = sc.parallelize(edges)

最后,您创建图表:

val graph = Graph(rddVertices,rddEdges)

我在自己的应用程序中有类似的代码,我试图按摩你需要的东西,但我无法保证这将是完美的。但它应该让你开始。

答案 2 :(得分:0)

如果您的文件是边缘列表格式,例如

---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:

    - name: 'Calling Python Code to reserve instance' 
      raw: python reserve-ec2-instance.py args

然后您可以简单地使用以下内容来计算顶点来自边缘端点的内容:

v1 v3
v2 v1
v3 v4
v5 v3

然而,因为它代表了' v4'它自己的意思是edgeListFile抛出异常

答案 3 :(得分:0)

你可以使用一个好的哈希函数将字符串值转换为long。