2013-05-05 41 views
13

Trong igraph, sau khi áp dụng thuật toán mô-đun hóa để tìm biểu đồ cộng đồng, tôi muốn vẽ bố cục mạng rõ ràng giúp hiển thị các cộng đồng riêng biệt và kết nối của chúng. Giống như "bố cục thuộc tính nhóm" trong Cytoscape: tôi muốn hiển thị các thành viên của mỗi nhóm/cộng đồng gần nhau và giữ khoảng cách giữa các nhóm/cộng đồng. Tôi không thể tìm thấy bất kỳ chức năng nào trong số igraph cung cấp tính năng này ra khỏi hộp. Trong khi đăng câu hỏi này tôi đã phát hiện ra một giải pháp d.i.y đơn giản, tôi sẽ đăng nó như một câu trả lời. Nhưng tôi tự hỏi nếu có bất kỳ khả năng tốt hơn, hoặc giải pháp phức tạp hơn?Làm cách nào để bố cục nhóm trong igraph?

Trả lời

4

Mở rộng trên gợi ý Gabor, tôi đã tạo ra chức năng này:

weight.community=function(row,membership,weigth.within,weight.between){ 
if(as.numeric(membership[which(names(membership)==row[1])])==as.numeric(membership[which(names(membership)==row[2])])){ 
weight=weigth.within 
}else{ 
weight=weight.between 
} 
return(weight) 
} 

Đơn giản chỉ cần áp dụng nó trên các hàng của ma trận của các cạnh của đồ thị của bạn (do get.edgelist(your_graph)) để thiết lập các trọng cạnh mới (thành viên là vector thành viên từ kết quả của bất kỳ thuật toán phát hiện cộng đồng):

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1) 

Sau đó, chỉ cần sử dụng một thuật toán bố trí chấp nhận trọng lượng cạnh như fruchterman.reingold theo đề nghị của Gabor Bạn có thể tinh chỉnh các đối trọng để OB. tain đồ thị bạn muốn. Ví dụ:

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1) 
g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight) 
plot(g) 

enter image description here

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,1000,1) 
g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight) 
plot(g) 

enter image description here

Lưu ý 1: tính minh bạch/màu sắc của các cạnh là các thông số khác của đồ thị của tôi. Tôi có các nút màu của cộng đồng để cho thấy rằng nó thực sự hoạt động.

Lưu ý 2: đảm bảo sử dụng membership(comm) và không comm$membership, trong đó comm là kết quả của thuật toán phát hiện cộng đồng (ví dụ: comm=leading.eigenvector.community(g)). Lý do là trong trường hợp đầu tiên, bạn nhận được một vector số với tên (những gì chúng ta muốn), và trong trường hợp thứ hai, cùng một vectơ không có tên.

Để nhận được sự đồng thuận của nhiều thuật toán phát hiện cộng đồng, hãy xem điều này function.

3

Chức năng layout.modular cung cấp một bố trí nhóm cho một đồ thị, từ kết quả của bất kỳ igraph phương pháp phát hiện cộng đồng:

c <- fastgreedy.community(G) 

layout.modular <- function(G,c){ 
nm <- length(levels(as.factor(c$membership))) 
gr <- 2 
while(gr^2<nm){ 
    gr <- gr+1 
} 
i <- j <- 0 
for(cc in levels(as.factor(c$membership))){ 
    F <- delete.vertices(G,c$membership!=cc) 
    F$layout <- layout.kamada.kawai(F) 
    F$layout <- layout.norm(F$layout, i,i+0.5,j,j+0.5) 
    G$layout[c$membership==cc,] <- F$layout 
    if(i==gr){ 
     i <- 0 
     if(j==gr){ 
      j <- 0 
     }else{ 
      j <- j+1 
     } 
    }else{ 
     i <- i+1 
    } 
} 
return(G$layout) 
} 

G$layout <- layout.modular(G,c) 
V(G)$color <- rainbow(length(levels(as.factor(c$membership))))[c$membership] 
plot(G) 
+1

tôi nhận được một lỗi nếu tôi thử phương pháp của bạn. Tôi chỉ thêm hai dòng ở trên mã của bạn để mô phỏng một mạng, tức là: 'thư viện (igraph); G <- barabasi.game (100, được chỉ định = FALSE) '. Thông báo lỗi cho biết: 'Lỗi trong bố cục G $ [c $ membership == cc,] <- F $ layout: số lượng không chính xác các bảng con trên ma trận' – majom

+0

Tôi cũng gặp lỗi tương tự. – imbenzene

+0

Xin lỗi, điều này xảy ra vì 'G $ layout' là' NULL'. Nếu bạn điền vào nó với bất kỳ ma trận nào có kích thước chính xác, hoặc đơn giản với một 'G $ layout <- layout.fruchterman.reingold (G)', thì mã sẽ chạy tốt. – deeenes

2

Một giải pháp sẽ được thiết lập trọng số cạnh của đồ thị, dựa trên các mô-đun hóa. Đặt các cạnh bên trong mô-đun cho một số trọng lượng lớn và giữa các cạnh mô-đun với một số trọng lượng nhỏ. Sau đó, gọi layout.fruchterman.reingold() hoặc bất kỳ thuật toán nào hỗ trợ trọng số cạnh.

Bạn có thể cần phải chơi một chút với các giá trị trọng lượng thực tế, bởi vì điều đó phụ thuộc vào biểu đồ của bạn.

+0

Hi Gabor, bạn có thể vui lòng xem [thread] liên quan này (http://stackoverflow.com/questions/31432176/potential-issue-with-new-igraph-layout-algorithms-r). Cảm ơn trước. – Antoine

5

Lấy cảm hứng về đề nghị Antoine, tôi tạo ra chức năng này:

edge.weights <- function(community, network, weight.within = 100, weight.between = 1) { 
bridges <- crossing(communities = community, graph = network) 
weights <- ifelse(test = bridges, yes = weight.between, no = weight.within) 
return(weights) 
} 

Chức năng hoạt động tương tự; chỉ cần đặt đối tượng cộng đồng của bạn vào khe cộng đồng, biểu đồ của bạn trong mạng. Tôi đã để lại weight.between = 1 và điều chỉnh giá trị weight.within.

Sau đó chuyển trọng lượng đến khe weight trong các nút:

E(graph)$weight <- edge.weights(community, graph) 

Cuối cùng sử dụng một thuật toán bố trí sử dụng trọng lượng như layout_with_fr (tên gọi mới của fruchterman.reingold trong igraph 1.0.1).

Tôi sử dụng mạng lưới câu lạc bộ karate của Zachary làm ví dụ.

library(igraph) 
library(igraphdata) 
#I load the network 
data(karate) 
#for reproducible purposes 
set.seed(23548723) 
karateLayout <- layout_with_fr(karate) 
par(mar = c(0,0,2,0)) 
plot(karate, vertex.size = 10, vertex.color = "steelblue4", edge.width = 1, 
vertex.label = NA, edge.color = "darkgrey", layout = karateLayout, 
main = "Zachary's karate club network") 

enter image description here

tôi phát hiện cộng đồng bằng cách đa cấp tối ưu hóa các mô đun với cluster_louvain chức năng:

Communitykarate <- cluster_louvain(karate) 

Tiếp theo đó là một sở thích cá nhân so với giá trị mặc định:

prettyColors <- c("turquoise4", "azure4", "olivedrab","deeppink4") 
communityColors <- prettyColors[membership(Communitykarate)] 

Biểu đồ với cộng đồng được làm nổi bật bằng màu sắc là:

plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10, 
vertex.label = NA, mark.groups = NULL, layout = karateLayout, col = communityColors, 
main = "Communities in Zachary's karate club network", 
edge.color = c("darkgrey","tomato2")crossing(Communitykarate, karate) + 1]) 

enter image description here

Bây giờ, ý nghĩa tại sao câu hỏi này tồn tại.

E(karate)$weight <- edge.weights(Communitykarate, karate) 
# I use the original layout as a base for the new one 
karateLayoutA <- layout_with_fr(karate, karateLayout) 
# the graph with the nodes grouped 
plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10, 
mark.groups = NULL, layout = karateLayoutA, vertex.label = NA, col = communityColors, 
c("darkgrey","tomato2")[crossing(Communitykarate, karate) + 1], 
main = "Communities in Zachary's karate club network (grouped)") 

enter image description here

Nếu bạn thử với trọng lượng hơn, bạn sẽ có có:

E(karate)$weight <- edge.weights(Communitykarate, karate, weight.within = 1000) 
karateLayoutB <- layout_with_fr(karate, karateLayout) 
plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10, 
mark.groups = NULL, layout = karateLayoutB, vertex.label = NA, col = communityColors, 
c("darkgrey","tomato2")[crossing(Communitykarate, karate) + 1], 
main = "Communities in Zachary's karate club network (grouped)") 

enter image description here

Các vấn đề liên quan