graphlayouts/0000755000176200001440000000000014164606432013002 5ustar liggesusersgraphlayouts/NAMESPACE0000644000176200001440000000163714162663334014232 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(annotate_circle) export(draw_circle) export(layout_as_backbone) export(layout_as_dynamic) export(layout_as_multilevel) export(layout_igraph_backbone) export(layout_igraph_centrality) export(layout_igraph_constrained_stress) export(layout_igraph_eigen) export(layout_igraph_focus) export(layout_igraph_multilevel) export(layout_igraph_pmds) export(layout_igraph_sparse_stress) export(layout_igraph_stress) export(layout_igraph_umap) export(layout_mirror) export(layout_rotate) export(layout_with_centrality) export(layout_with_constrained_stress) export(layout_with_constrained_stress3D) export(layout_with_eigen) export(layout_with_focus) export(layout_with_pmds) export(layout_with_sparse_stress) export(layout_with_stress) export(layout_with_stress3D) export(layout_with_umap) export(reorder_edges) importFrom(Rcpp,sourceCpp) useDynLib(graphlayouts, .registration = TRUE) graphlayouts/LICENSE0000644000176200001440000000005213447644144014011 0ustar liggesusersYEAR: 2019 COPYRIGHT HOLDER: David Schoch graphlayouts/README.md0000644000176200001440000002242114162151502014251 0ustar liggesusers # graphlayouts [![R-CMD-check](https://github.com/schochastics/graphlayouts/workflows/R-CMD-check/badge.svg)](https://github.com/schochastics/graphlayouts/actions) [![CRAN status](https://www.r-pkg.org/badges/version/graphlayouts)](https://cran.r-project.org/package=graphlayouts) [![Downloads](https://cranlogs.r-pkg.org/badges/graphlayouts)](https://CRAN.R-project.org/package=graphlayouts) This package implements some graph layout algorithms that are not available in `igraph`. **A detailed introductory tutorial for graphlayouts and ggraph can be found [here](http://mr.schochastics.net/netVizR.html).** The package implements the following algorithms: - Stress majorization ([Paper](https://graphviz.gitlab.io/_pages/Documentation/GKN04.pdf)) - Quadrilateral backbone layout ([Paper](https://jgaa.info/accepted/2015/NocajOrtmannBrandes2015.19.2.pdf)) - flexible radial layouts ([Paper](https://jgaa.info/accepted/2011/BrandesPich2011.15.1.pdf)) - sparse stress ([Paper](https://arxiv.org/abs/1608.08909)) - pivot MDS ([Paper](https://kops.uni-konstanz.de/bitstream/handle/123456789/5741/bp_empmdsld_06.pdf?sequence=1&isAllowed=y)) - dynamic layout for longitudinal data ([Paper](https://kops.uni-konstanz.de/bitstream/handle/123456789/20924/Brandes_209246.pdf?sequence=2)) - spectral layouts (adjacency/Laplacian) - a simple multilevel layout - a layout algorithm using UMAP ## Install ``` r # dev version remotes::install_github("schochastics/graphlayouts") #CRAN install.packages("graphlayouts") ``` ## Stress Majorization: Connected Network *This example is a bit of a special case since it exploits some weird issues in igraph.* ``` r library(igraph) library(ggraph) library(graphlayouts) set.seed(666) pa <- sample_pa(1000,1,1,directed = F) ggraph(pa,layout = "nicely")+ geom_edge_link0(width=0.2,colour="grey")+ geom_node_point(col="black",size=0.3)+ theme_graph() ``` ``` r ggraph(pa,layout="stress")+ geom_edge_link0(width=0.2,colour="grey")+ geom_node_point(col="black",size=0.3)+ theme_graph() ``` ## Stress Majorization: Unconnected Network Stress majorization also works for networks with several components. It relies on a bin packing algorithm to efficiently put the components in a rectangle, rather than a circle. ``` r set.seed(666) g <- disjoint_union( sample_pa(10,directed = F), sample_pa(20,directed = F), sample_pa(30,directed = F), sample_pa(40,directed = F), sample_pa(50,directed = F), sample_pa(60,directed = F), sample_pa(80,directed = F) ) ggraph(g,layout = "nicely") + geom_edge_link0() + geom_node_point() + theme_graph() ``` ``` r ggraph(g, layout = "stress",bbox = 40) + geom_edge_link0() + geom_node_point() + theme_graph() ``` ## Backbone Layout Backbone layouts are helpful for drawing hairballs. ``` r set.seed(665) #create network with a group structure g <- sample_islands(9,40,0.4,15) g <- simplify(g) V(g)$grp <- as.character(rep(1:9,each=40)) ggraph(g,layout = "stress")+ geom_edge_link0(colour=rgb(0,0,0,0.5),width=0.1)+ geom_node_point(aes(col=grp))+ scale_color_brewer(palette = "Set1")+ theme_graph()+ theme(legend.position = "none") ``` The backbone layout helps to uncover potential group structures based on edge embeddedness and puts more emphasis on this structure in the layout. ``` r bb <- layout_as_backbone(g,keep=0.4) E(g)$col <- F E(g)$col[bb$backbone] <- T ggraph(g,layout="manual",x=bb$xy[,1],y=bb$xy[,2])+ geom_edge_link0(aes(col=col),width=0.1)+ geom_node_point(aes(col=grp))+ scale_color_brewer(palette = "Set1")+ scale_edge_color_manual(values=c(rgb(0,0,0,0.3),rgb(0,0,0,1)))+ theme_graph()+ theme(legend.position = "none") ``` ## Radial Layout with Focal Node The function `layout_with_focus()` creates a radial layout around a focal node. All nodes with the same distance from the focal node are on the same circle. ``` r library(igraphdata) library(patchwork) data("karate") p1 <- ggraph(karate,layout = "focus",focus = 1) + draw_circle(use = "focus",max.circle = 3)+ geom_edge_link0(edge_color="black",edge_width=0.3)+ geom_node_point(aes(fill=as.factor(Faction)),size=2,shape=21)+ scale_fill_manual(values=c("#8B2323", "#EEAD0E"))+ theme_graph()+ theme(legend.position = "none")+ coord_fixed()+ labs(title= "Focus on Mr. Hi") p2 <- ggraph(karate,layout = "focus",focus = 34) + draw_circle(use = "focus",max.circle = 4)+ geom_edge_link0(edge_color="black",edge_width=0.3)+ geom_node_point(aes(fill=as.factor(Faction)),size=2,shape=21)+ scale_fill_manual(values=c("#8B2323", "#EEAD0E"))+ theme_graph()+ theme(legend.position = "none")+ coord_fixed()+ labs(title= "Focus on John A.") p1+p2 ``` ## Radial Centrality Layout The function `layout_with_centrality` creates a radial layout around the node with the highest centrality value. The further outside a node is, the more peripheral it is. ``` r library(igraphdata) library(patchwork) data("karate") bc <- betweenness(karate) p1 <- ggraph(karate,layout = "centrality", centrality = bc, tseq = seq(0,1,0.15)) + draw_circle(use = "cent") + annotate_circle(bc,format="",pos="bottom") + geom_edge_link0(edge_color="black",edge_width=0.3)+ geom_node_point(aes(fill=as.factor(Faction)),size=2,shape=21)+ scale_fill_manual(values=c("#8B2323", "#EEAD0E"))+ theme_graph()+ theme(legend.position = "none")+ coord_fixed()+ labs(title="betweenness centrality") cc <- closeness(karate) p2 <- ggraph(karate,layout = "centrality", centrality = cc, tseq = seq(0,1,0.2)) + draw_circle(use = "cent") + annotate_circle(cc,format="scientific",pos="bottom") + geom_edge_link0(edge_color="black",edge_width=0.3)+ geom_node_point(aes(fill=as.factor(Faction)),size=2,shape=21)+ scale_fill_manual(values=c("#8B2323", "#EEAD0E"))+ theme_graph()+ theme(legend.position = "none")+ coord_fixed()+ labs(title="closeness centrality") p1+p2 ``` ## Large graphs `graphlayouts` implements two algorithms for visualizing large networks (\<100k nodes). `layout_with_pmds()` is similar to `layout_with_mds()` but performs the multidimensional scaling only with a small number of pivot nodes. Usually, 50-100 are enough to obtain similar results to the full MDS. `layout_with_sparse_stress()` performs stress majorization only with a small number of pivots (\~50-100). The runtime performance is inferior to pivotMDS but the quality is far superior. A comparison of runtimes and layout quality can be found in the [wiki](https://github.com/schochastics/graphlayouts/wiki/) **tl;dr**: both layout algorithms appear to be faster than the fastest igraph algorithm `layout_with_drl()`. Below are two examples of layouts generated for large graphs using `layout_with_sparse_stress()` A retweet network with 18k nodes and 61k edges A co-citation network with 12k nodes and 68k edges ## dynamic layouts `layout_as_dynamic()` allows you to visualize snapshots of longitudinal network data. Nodes are anchored with a reference layout and only moved slightly in each wave depending on deleted/added edges. In this way, it is easy to track down specific nodes throughout time. Use `patchwork` to put the individual plots next to each other. ``` r library(patchwork) #gList is a list of longitudinal networks. xy <- layout_as_dynamic(gList,alpha = 0.2) pList <- vector("list",length(gList)) for(i in 1:length(gList)){ pList[[i]] <- ggraph(gList[[i]],layout="manual",x=xy[[i]][,1],y=xy[[i]][,2])+ geom_edge_link0(edge_width=0.6,edge_colour="grey66")+ geom_node_point(shape=21,aes(fill=smoking),size=3)+ geom_node_text(aes(label=1:50),repel = T)+ scale_fill_manual(values=c("forestgreen","grey25","firebrick"),guide=ifelse(i!=2,FALSE,"legend"))+ theme_graph()+ theme(legend.position="bottom")+ labs(title=paste0("Wave ",i)) } Reduce("+",pList)+ plot_annotation(title="Friendship network",theme = theme(title = element_text(family="Arial Narrow",face = "bold",size=16))) ``` ## Layout manipulation The functions `layout_mirror()` and `layout_rotate()` can be used to manipulate an existing layout graphlayouts/data/0000755000176200001440000000000013650032646013712 5ustar liggesusersgraphlayouts/data/multilvl_ex.rda0000644000176200001440000002155313650032646016754 0ustar liggesusersBZh91AY&SYI݌}LDUWDT\DDDDDDDDdE40@@HD(@*$H"(U@Ɂ1 ==&MCM@h4@4d*T~oO)*4z 44 @U=CMEHdMM C@FFi&&h`# 2`&0#d !B M 4CM40F0M M2 * L j~ 1SI=OĞOSOB!O& 6SM2@dh='ꙩ k,C%D#Y# DF`"X" ЪHRUu"."(Wk.OQ ]rAETE]X.ut`UD`BXB.dYeX,YdeE,!ad,B,B,Y,ʊ*"ȊnE) v tT\*,0EYw.CbL FJYWYb]eB"]d.YA,`+vCYeD"J˪UoYfhTY.+"d`E,e5]aʲEXĺ5]t,Ru)a .]DYg!()OԲ6.łYt] !ƅ,b(ɉE ?܋Ҋ2P"?Rꥋ]B,e(ʪbWY"噂QuR#QF Q0`Y&lY T1QQFłQQD`V XҢ @f`ͥUUu] eͫ] +%\-,˩,X,C$bYyQ)KC6&-)ś%hYdEج`LX5!"UYtdȫ0"ȋBYY].dl31`ˬ3b͛6g]v6lX6,2dɓK1]c&Hؘ (ɋ `Y#'5٣LرEf2]ȌٳdЋ43"Fl5f=Vl_QœCbXY15.6{{&VYi̻[sc7K7ވ͵śCZmM-ω'»kM 퍭1vL\lldb[VXlq76CKcɓK&m55~675,M뵬ŋkk{6L743d͵fɩv8W,ͭc?+S{&Ɨ,43fŵfٷ1Yv ML lp.]KC k68Zo]cb4,ũk6 i]B[ZZ-Q]v kj]͹467vMVjdű3p6758ۗ8YjY4iimp!n6#{&vp782ioYͽq1nodŹKS'sƶƖ cj,ԌMLZۚn?C{ci?ŭmkYڻj5#=q4{{[K渚kq8%Qbz-Mu:܏}u= .f'bq=Giw68.O#riy`:.wm,}Gkzd[}q4{&k69^SE]CYnvf͓c;ot;ڜ畓;<.sCSub;lzcIDEfn [-^Fc`uv;\p#if}v#ccdw;"+[ֻ[mkfbr7Z7סkv]NcCkkSjhu= K5Zkjt=nns[,kv<:zWcKv.r<mfnr6wWw8 λw75:NqwMRsYyiq}tqvng1ػQj99dhuzyiv6Kw]#{ysv#&dxkgy_mw*t&vep=nv= WY>%fFe_cj2G#xnfӶ-dm4T.ø_^vn6뉾[avȴu..4ʙӰqiV&Mn7W˶o15EdqZb\TU F EY)-noCSMfK4dԱZ`Fh} fd.ͭf ɛdͪ1|m 3YbbZե3`.ؚhbY?CSj,Ħhk"5'r.eژY l2`ͭdb+΅ 47Y" .mG!e?u8ZFHɃ`j`T#!`5\˾U!tVߕD+c&/TS'DR?:B*3`!ڲOIscf/18\k`5IܳEWY^Uz;]jlY_1UOUh{*Kz|Ǡ5?xYW!< +ʊV敇EY[UU,<5lB"8`S7"_H:[\ŁtI\ 7?Ye!O8YFifOsB^VM`ȳ٬0C/>7󿡃(́F ,.ɥU^TYVև@5?g3BXqDwEs{yo!V'[|5=-> Oym#26q?)~uOX~*WIxY|s zOY<SOzj/9^RqyD1g6Odɓ&OpPiɲܵ*?ɛ??QJ*U(z*)UUUURBPJ̟kR"WȈEYU0WV,\ĈE1"!ȄYtBdBBQLQQY DT"!Q,%P""PDA GTًJG>g7XZUJUU!((+jXJwraFjUQJ+ ZU*UDQQ DQDQQZ*QDTr;T !ETB"UUQDRBDAUQ"!U]  DA*""GhШDRT.,?UR!B!vE"DU"d *EDD"""UbB!DAB@G>D|FM O_'ItG몫@*ez6M a&jkWV~kOWw~4?zU,g?Gqs랺U*yx^.KQm:]-3z9`>Cs{8Yʦ]]]v]jNSގӠ;Ut:b:E`Y1d/O~cTQ,E,be*?q+mfo ?C` /b3nY<+]=yiYMf3:ҵC"LDd)dI^d2$d2 C!r1up+F, l0b̥{,:γu]gZ38gYuWA޳f Z [s>.--0-*ZR`0 U`VVr:Mjo+++NYYZEeeYk6I${%伕Y~i/b+-ͫͭͭ-mk!K"RȲ,/uYeYeYe,NU6-]u[[[[[Z_sڻkEDDDDDDDDg *&M u]mp8ZZȈ>G;wz2dr)N@mmG#r뮻r9-mh۲ȏȈoUP&]vj0bɵu]1)QJڻ]v֦֖e诚{ =|/R_I|vǘ+hsP3]eVdY MnC%jl|OԳ?+Y~S*#T~? #TGߐ?">WU>Gs'+w!>S|W|ȯ!};{Ws9ϼU~+UH`TBET "DB 좘">UBAUVB)ED* Q"*"DBB"* "D(UDU !QHB"*"")QBT!!*"TBD"""!DUED!dYPDEBE"DR"*DED*")DTEBTDBQ**(*U!QQ"E"PDBEED!H"*"B"""B"UTE TEBHR"B)!UQE"*!(RB!QDB" E*UUDTTDE"!HB"ETBB"DJ"DDUDRJEDTB!"REUR"R(A!TDUTDR*TAQ*TEPE"!Q RUD@D""DRHD*)D("*DD"Q!Q EDQU")TE"*Q AQ D* "(" AUTEU")HE" @D)EDUTEB"BUT*!TEUDU4HYHE*UUUQ""UQ UHRD E(* DDDPD)HUDU TB *UTBHU"*H"R""!UH"UDRTB"UeQUq9c2b'rSʯ)GQ^s9^W#Ťi4d#5B D)]JtjXZo^Xaai5^a*TT******NQQQQw㺝! R DEUB D)B D)u&q&L¨mY#:o":luγus+p]S6i`Œ3g=U}d}w߬`,")eu>'čOvOvCpĹa}Kz(\o%g2y;sW/]?37³K~$Gu3oi?/i='}}TzWzOJzOI='^ozOI='zOJ'zOIgzCp=='@(p' BK.QGx;zWyWyήssfs9*Yhf*==atGҥ^/;I ֒INiwSI:t'';s ɉG*QeUSCKAŰW09c9c9c9LXb){b, {1]}F ذ}כּ]{}Qi+i+m*V3Q17y+}*e " eSyp7O~n7՛'a:͇Y7YWZγ:S9NW)Jՙt=erXzY,XX OY]geYlh)?LQQYv«eK6Vdت`в},M [hd]J>>5 >G(`sjYCJf՟aFgSVjbm7>wj]#c+#K.YoS=}e|iw|}7| >|*|&|'|'|'|'|'yj|.7cfaŊ,Vu":uG!uJ9NSr24ZhRoJKjT%PZPP+9|oF