Các thao tác biến đổi đồ thị
Đồ thị trong GraphX cung cấp hai phương thức chính để biến đổi thành phần:
mapVertices(): Ánh xạ lại thuộc tính đỉnh, tạo đồ thị mớimapEdges(): Biến đổi trọng số cạnh, trả về đồ thị đã cập nhật
println("Biến đổi đỉnh: tăng tuổi thêm 5")
doThi.mapVertices((id, info) => (id, (info._1, info._2 + 5)))
.vertices.collect()
.foreach(v => println(s"${v._2._1} - ${v._2._2} tuổi"))
println("Biến đổi cạnh: nhân đôi trọng số")
doThi.mapEdges(canh => canh.attr * 2)
.edges.collect()
.foreach(e => println(s"${e.srcId} → ${e.dstId}: ${e.attr}"))
Kết quả thực thi:
Biến đổi đỉnh: tăng tuổi thêm 5 Peter - 32 tuổi Kate - 24 tuổi Henry - 27 tuổi Alice - 38 tuổi Charlie - 55 tuổi Mike - 35 tuổi Biến đổi cạnh: nhân đôi trọng số 2 → 1: 10 2 → 4: 4 3 → 2: 14 3 → 6: 6 4 → 1: 2 5 → 2: 6 5 → 3: 16 5 → 6: 16
Tác vụ lọc cấu trúc đồ thị
Phương thức subgraph() cho phép trích xuất đồ thị con dựa trên điều kiện đỉnh:
println("Đồ thị con với người trên 26 tuổi")
val doThiCon = doThi.subgraph(vpred = (id, info) => info._2 > 26)
println("Danh sách đỉnh:")
doThiCon.vertices.collect().foreach(v =>
println(s"${v._2._1} (${v._2._2} tuổi)"))
println("Danh sách cạnh:")
doThiCon.edges.collect().foreach(e =>
println(s"${e.srcId} → ${e.dstId} (trọng số: ${e.attr})"))
Đầu ra mẫu:
Đồ thị con với người trên 26 tuổi Danh sách đỉnh: Peter (32 tuổi) Henry (27 tuổi) Alice (38 tuổi) Charlie (55 tuổi) Mike (35 tuổi) Danh sách cạnh: 2 → 1 (trọng số: 5) 2 → 4 (trọng số: 2) 3 → 2 (trọng số: 7) 4 → 1 (trọng số: 1) 5 → 2 (trọng số: 3) 5 → 3 (trọng số: 8)
Kết nối đồ thị với thuộc tính mở rộng
Sử dụng outerJoinVertices() để kết hợp thông tin từ đồ thị phụ:
case class ThongTinNguoi(ten: String, tuoi: Int, bacVao: Int, bacRa: Int)
val doThiGoc = doThi.mapVertices((id, info) =>
ThongTinNguoi(info._1, info._2, 0, 0))
val doThiHoanChinh = doThiGoc.outerJoinVertices(doThiGoc.inDegrees) {
(id, nguoi, bacVao) =>
ThongTinNguoi(nguoi.ten, nguoi.tuoi, bacVao.getOrElse(0), nguoi.bacRa)
}.outerJoinVertices(doThiGoc.outDegrees) {
(id, nguoi, bacRa) =>
ThongTinNguoi(nguoi.ten, nguoi.tuoi, nguoi.bacVao, bacRa.getOrElse(0))
}
println("Thông tin độ kết nối:")
doThiHoanChinh.vertices.collect().foreach { case (_, tt) =>
println(s"${tt.ten}: bậc vào=${tt.bacVao}, bậc ra=${tt.bacRa}")
}
println("Người có bậc vào bằng bậc ra:")
doThiHoanChinh.vertices.filter { case (_, tt) =>
tt.bacVao == tt.bacRa
}.collect().foreach { case (_, tt) => println(tt.ten) }
Kết quả xử lý:
Thông tin độ kết nối: Peter: bậc vào=1, bậc ra=1 Kate: bậc vào=2, bậc ra=0 Henry: bậc vào=2, bậc ra=2 Alice: bậc vào=2, bậc ra=0 Charlie: bậc vào=1, bậc ra=2 Mike: bậc vào=0, bậc ra=3 Người có bậc vào bằng bậc ra: Peter Henry