Aracılığıyla paylaş


GraphFrames kullanıcı kılavuzu - Scala

Bu makalede GraphFrames Kullanıcı Kılavuzu'ndaki örnekler gösterilmektedir.

import org.apache.spark.sql._
import org.apache.spark.sql.functions._
import org.graphframes._

GraphFrame'ler Oluşturma

Köşe ve uç Veri Çerçevelerinden GraphFrame'ler oluşturabilirsiniz.

  • Köşe Veri Çerçevesi: Köşe DataFrame, grafikteki her köşe için benzersiz kimlikleri belirten adlı id özel bir sütun içermelidir.
  • Edge DataFrame: Bir kenar DataFrame iki özel sütun içermelidir: src (kenarın kaynak köşe kimliği) ve dst (kenarın hedef köşe kimliği).

Her iki DataFrame'in de rastgele başka sütunları olabilir. Bu sütunlar köşe ve kenar özniteliklerini temsil edebilir.

Köşeleri ve kenarları oluşturma

// Vertex DataFrame
val v = spark.createDataFrame(List(
  ("a", "Alice", 34),
  ("b", "Bob", 36),
  ("c", "Charlie", 30),
  ("d", "David", 29),
  ("e", "Esther", 32),
  ("f", "Fanny", 36),
  ("g", "Gabby", 60)
)).toDF("id", "name", "age")
// Edge DataFrame
val e = spark.createDataFrame(List(
  ("a", "b", "friend"),
  ("b", "c", "follow"),
  ("c", "b", "follow"),
  ("f", "c", "follow"),
  ("e", "f", "follow"),
  ("e", "d", "friend"),
  ("d", "a", "friend"),
  ("a", "e", "friend")
)).toDF("src", "dst", "relationship")

Şimdi bu köşelerden ve şu kenarlardan bir grafik oluşturalım:

val g = GraphFrame(v, e)
// This example graph also comes with the GraphFrames package.
// val g = examples.Graphs.friends

Temel grafik ve DataFrame sorguları

GraphFrame'ler düğüm derecesi gibi basit graf sorguları sağlar.

Ayrıca GraphFrame'ler grafları köşe ve uç DataFrame çiftleri olarak temsil ettiğinden, doğrudan köşe ve uç DataFrame'lerde güçlü sorgular yapmak kolaydır. Bu DataFrame'ler GraphFrame'de köşe ve kenar alanları olarak kullanılabilir.

display(g.vertices)
display(g.edges)

Köşelerin gelen derecesi:

display(g.inDegrees)

Köşelerin giden derecesi:

display(g.outDegrees)

Köşelerin derecesi:

display(g.degrees)

Sorguları doğrudan DataFrame köşelerinde çalıştırabilirsiniz. Örneğin, grafikte en genç kişinin yaşını bulabiliriz:

val youngest = g.vertices.groupBy().min("age")
display(youngest)

Benzer şekilde, DataFrame uçlarında da sorgu çalıştırabilirsiniz. Örneğin, grafikteki 'takip et' ilişkilerini sayalım:

val numFollows = g.edges.filter("relationship = 'follow'").count()

Motif bulma

Motifleri kullanarak kenarlar ve köşeler içeren daha karmaşık ilişkiler oluşturun. Aşağıdaki hücre, aralarında her iki yönde de kenarları olan köşe çiftlerini bulur. Sonuç, sütun adlarının motif tuşları olduğu bir DataFrame'dir.

API hakkında daha fazla ayrıntı için GraphFrame Kullanıcı Kılavuzu'na göz atın.

// Search for pairs of vertices with edges in both directions between them.
val motifs = g.find("(a)-[e]->(b); (b)-[e2]->(a)")
display(motifs)

Sonuç bir DataFrame olduğundan, motifin üzerinde daha karmaşık sorgular oluşturabilirsiniz. Bir kişinin 30'dan büyük olduğu tüm karşılıklı ilişkileri bulalım:

val filtered = motifs.filter("b.age > 30")
display(filtered)

Durum bilgisi olan sorgular

Yukarıdaki örneklerde olduğu gibi çoğu motif sorgusu durum bilgisi olmayan ve ifade etmek kolaydır. Sonraki örneklerde, motifteki bir yol boyunca durum taşıyan daha karmaşık sorgular gösterilmektedir. Bu sorguları, GraphFrame motif bulgusunun sonucu filtrelerle birleştirerek ifade edin. Burada filtreler, bir dizi DataFrame sütunu oluşturmak için sıralı işlemleri kullanır.

Örneğin, bir işlev dizisi tarafından tanımlanan bazı özelliklere sahip 4 köşeli bir zincir tanımlamak istediğinizi varsayalım. Diğer bir ifadeyle, 4 köşeli zincirler a->b->c->darasında, bu karmaşık filtreyle eşleşen zincir alt kümesini tanımlayın:

  • Yolda başlatma durumu.
  • A köşesini temel alarak durumu güncelleştirin.
  • B köşesini temel alarak durumu güncelleştirin.
  • Vb. c ve d için.
  • Son durum bazı koşullarla eşleşiyorsa filtre zinciri kabul eder.

Aşağıdaki kod parçacıkları, 3 kenardan en az 2'sinin "arkadaş" ilişkiler olması için 4 köşeden oluşan zincirleri tanımladığımız bu işlemi göstermektedir. Bu örnekte durum, "arkadaş" kenarlarının geçerli sayısıdır; genel olarak herhangi bir DataFrame sütunu olabilir.

// Find chains of 4 vertices.
val chain4 = g.find("(a)-[ab]->(b); (b)-[bc]->(c); (c)-[cd]->(d)")

// Query on sequence, with state (cnt)
//  (a) Define method for updating state given the next element of the motif.
def sumFriends(cnt: Column, relationship: Column): Column = {
  when(relationship === "friend", cnt + 1).otherwise(cnt)
}
//  (b) Use sequence operation to apply method to sequence of elements in motif.
//      In this case, the elements are the 3 edges.
val condition = Seq("ab", "bc", "cd").
  foldLeft(lit(0))((cnt, e) => sumFriends(cnt, col(e)("relationship")))
//  (c) Apply filter to DataFrame.
val chainWith2Friends2 = chain4.where(condition >= 2)
display(chainWith2Friends2)

Alt Yazılar

GraphFrames, kenarlarda ve köşelerde filtreleme yaparak alt grafikler oluşturmaya yönelik API'ler sağlar. Bu filtreler birlikte oluşturulabilir. Örneğin, aşağıdaki alt yazı yalnızca arkadaş olan ve 30 yaşından büyük kişileri içerir.

// Select subgraph of users older than 30, and edges of type "friend"
val g2 = g
  .filterEdges("relationship = 'friend'")
  .filterVertices("age > 30")
  .dropIsolatedVertices()

Karmaşık üçlü filtreler

Aşağıdaki örnekte, bir kenarda ve "src" ve "dst" köşelerinde çalışan üçlü filtreleri temel alan bir alt grafiğin nasıl seçildiğini gösterilmektedir. Bu örneği daha karmaşık motifler kullanarak üçlülerin ötesine geçmek için genişletmek basittir.

// Select subgraph based on edges "e" of type "follow"
// pointing from a younger user "a" to an older user "b".
val paths = g.find("(a)-[e]->(b)")
  .filter("e.relationship = 'follow'")
  .filter("a.age < b.age")
// "paths" contains vertex info. Extract the edges.
val e2 = paths.select("e.src", "e.dst", "e.relationship")
// In Spark 1.5+, the user may simplify this call:
//  val e2 = paths.select("e.*")

// Construct the subgraph
val g2 = GraphFrame(g.vertices, e2)
display(g2.vertices)
display(g2.edges)

Standart grafik algoritmaları

Bu bölümde GraphFrame'lerde yerleşik olarak bulunan standart graf algoritmaları açıklanmaktadır.

İçerik öncelikli arama (BFS)

32 yaşındaki < kullanıcılar için "Esther"den arama yapın.

val paths: DataFrame = g.bfs.fromExpr("name = 'Esther'").toExpr("age < 32").run()
display(paths)

Arama ayrıca kenar filtrelerini ve maksimum yol uzunluklarını sınırlayabilir.

val filteredPaths = g.bfs.fromExpr("name = 'Esther'").toExpr("age < 32")
  .edgeFilter("relationship != 'friend'")
  .maxPathLength(3)
  .run()
display(filteredPaths)

Bağlı bileşenler

Her köşenin bağlı bileşen üyeliğini hesaplayıp her köşeye bir bileşen kimliği atanmış bir grafik döndürür.

val result = g.connectedComponents.run() // doesn't work on Spark 1.4
display(result)

Güçlü bağlı bileşenler

Her köşenin güçlü bağlı bileşenini (SCC) hesaplayıp her köşenin ilgili köşeyi içeren SCC'ye atandığı bir graf döndürür.

val result = g.stronglyConnectedComponents.maxIter(10).run()
display(result.orderBy("component"))

Etiket yayma

Ağlardaki toplulukları algılamak için statik Etiket Yayma Algoritması çalıştırın.

Ağdaki her düğüm başlangıçta kendi topluluğuna atanır. Her üst adımda düğümler, topluluk ilişkilendirmelerini tüm komşulara gönderir ve durumlarını gelen iletilerin mod topluluk ilişkisine güncelleştirir.

LPA, grafikler için standart bir topluluk algılama algoritmasıdır. Hesaplama açısından ucuzdur, ancak (1) yakınsama garanti edilmediğinden ve (2) önemsiz çözümlerle sonuçlanabilir (tüm düğümler tek bir toplulukta tanımlanır).

val result = g.labelPropagation.maxIter(5).run()
display(result.orderBy("label"))

Pagerank

Bağlantılara göre grafikteki önemli köşeleri belirleme.

// Run PageRank until convergence to tolerance "tol".
val results = g.pageRank.resetProbability(0.15).tol(0.01).run()
display(results.vertices)
display(results.edges)
// Run PageRank for a fixed number of iterations.
val results2 = g.pageRank.resetProbability(0.15).maxIter(10).run()
display(results2.vertices)
// Run PageRank personalized for vertex "a"
val results3 = g.pageRank.resetProbability(0.15).maxIter(10).sourceId("a").run()
display(results3.vertices)

En kısa yollar

Yer işaretlerinin köşe kimliğine göre belirttiği belirli yer işareti köşeleri kümesine giden en kısa yolları hesaplar.

val paths = g.shortestPaths.landmarks(Seq("a", "d")).run()
display(paths)

Üçgen sayma

Her köşeden geçen üçgen sayısını hesaplar.

import org.graphframes.examples
val g: GraphFrame = examples.Graphs.friends  // get example graph

val results = g.triangleCount.run()
results.select("id", "count").show()