Skip to content

ggraph::geom_conn_bundle() sometimes does not match other information with "from" and "to" columns correctly #249

@zhuxr11

Description

@zhuxr11

Recently, I am using ggraph to create circular bundle graphs. I noticed that in ggraph::geom_conn_bundle(), if I wanted to specify information such as the color of connections, they sometimes did not match the correct connections. For example, in the following ggraph, I wanted to create 3 connections between node pairs (30,74), (34,71) and (35,70), with colors "A", "B", "C" respectively (A = red, B = green, C = blue, as shown in ggplot 0).

ggraph 1: source nodes were permuted in the ascending order: (30,74), (34,71) and (35,70), with colors "A", "B", "C" respectively, I got the correct matching.

ggraph 2: within node group re-ordering along with their color information: (30,74), (35,70) and (34,71), with colors "A", "C", "B" respectively, I got a wrong matching of the colors to the connections.

ggraph 3: across node groups re-ordering along with their color information: (34,71), (35,70) and (30,74), with colors "B", "C", "A" respectively, I got a wrong matching of the colors to the connections.

ggraph 4: across node groups re-ordering along with their color information: (34,71), (30,74) and (35,70), with colors "B", "A", "C" respectively, I got another wrong matching of the colors to the connections.

It is somewhat hard to understand if I re-order the connections with their corresponding properties (e.g. color), I get different matching of connections and their properties. I spent quite an amount of time to figure out that this problem can be solved if I permute the source nodes group in the ascending order and also the source nodes in the ascending order within each group. But I think the connection mapping should work correctly with any order of connections provided. Could you please tell me what I'm not handling correctly?

ggplot 0: revealing default color mapping to "A", "B" and "C"
enter image description here

ggraph 1: connections (30,74), (34,71) and (35,70), with colors "A", "B", "C" respectively (ordered source nodes -> correct matching)
enter image description here

ggraph 2: connections (30,74), (35,70) and (34,71), with colors "A", "C", "B" respectively (intra-group reorder -> wrong matching)
enter image description here

ggraph 3: connections (34,71), (35,70) and (30,74), with colors "B", "C", "A" respectively (inter-group reorder -> wrong matching)
enter image description here

ggraph 4: connections (34,71), (30,74) and (35,70), with colors "B", "A", "C" respectively (another inter-group reorder -> wrong matching)
enter image description here

# Libraries
library(ggraph)
library(igraph)
library(tidyverse)
library(RColorBrewer)

# create a data frame giving the hierarchical structure of your individuals
set.seed(1234)
d1 <- data.frame(from="origin", to=paste("group", seq(1,10), sep=""))
d2 <- data.frame(from=rep(d1$to, each=10), to=paste("subgroup", seq(1,100), sep="_"))
edges <- rbind(d1, d2)
edges

# create a vertices data.frame. One line per object of our hierarchy
vertices  <-  data.frame(
  name = unique(c(as.character(edges$from), as.character(edges$to))) , 
  value = runif(111)
) 
# Let's add a column with the group of each name. It will be useful later to color points
vertices$group  <-  edges$from[ match( vertices$name, edges$to ) ]
#Let's add information concerning the label we are going to add: angle, horizontal adjustement and potential flip
#calculate the ANGLE of the labels
vertices$id <- 1:nrow(vertices)
vertices

# Create a graph object
mygraph <- igraph::graph_from_data_frame( edges, vertices=vertices )

# See the color map with ggplot
tribble(~ y, ~ col,
        2, "A",
        1, "B",
        0, "C") %>%
  ggplot() +
  geom_hline(aes(yintercept=y, color=col))

# Plot ggraph 1 with conn = 30-74 (color "A"), 34-71 (color "B"), 35-70 (color "C")
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
  geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, color = group), show.legend = FALSE) +
  geom_conn_bundle(data = get_con(from = c(30, 34, 35), to = c(74, 71, 70), col = c("A", "B", "C")), alpha=1, aes(color=col), width = 0.9) +
  geom_node_text(aes(x = x*1.1, y=y*1.1, filter = leaf, label=id, angle = node_angle(x, y)), size=2.5, alpha=1) +
  theme_void() +
  coord_fixed() +
  theme(
    # legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
  expand_limits(x = c(-1.2, 1.2), y = c(-1.2, 1.2))

# Plot ggraph 2 with conn = 30-74 (color "A"), 35-70 (color "C"), 34-71 (color "B")
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
  geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, color = group), show.legend = FALSE) +
  geom_conn_bundle(data = get_con(from = c(30, 35, 34), to = c(74, 70, 71), col = c("A", "C", "B")), alpha=1, aes(color=col), width = 0.9) +
  geom_node_text(aes(x = x*1.1, y=y*1.1, filter = leaf, label=id, angle = node_angle(x, y)), size=2.5, alpha=1) +
  theme_void() +
  coord_fixed() +
  theme(
    # legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
  expand_limits(x = c(-1.2, 1.2), y = c(-1.2, 1.2))

# Plot ggraph 3 with conn = 34-71 (color "B"), 35-70 (color "C"), 30-74 (color "A")
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
  geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, color = group), show.legend = FALSE) +
  geom_conn_bundle(data = get_con(from = c(34, 35, 30), to = c(71, 70, 74), col = c("B", "C", "A")), alpha=1, aes(color=col), width = 0.9) +
  geom_node_text(aes(x = x*1.1, y=y*1.1, filter = leaf, label=id, angle = node_angle(x, y)), size=2.5, alpha=1) +
  theme_void() +
  coord_fixed() +
  theme(
    # legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
  expand_limits(x = c(-1.2, 1.2), y = c(-1.2, 1.2))

# Plot ggraph 4 with conn = 34-71 (color "B"), 30-74 (color "A"), 35-70 (color "C")
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) + 
  geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, color = group), show.legend = FALSE) +
  geom_conn_bundle(data = get_con(from = c(34, 30, 35), to = c(71, 74, 70), col = c("B", "A", "C")), alpha=1, aes(color=col), width = 0.9) +
  geom_node_text(aes(x = x*1.1, y=y*1.1, filter = leaf, label=id, angle = node_angle(x, y)), size=2.5, alpha=1) +
  theme_void() +
  coord_fixed() +
  theme(
    # legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
  expand_limits(x = c(-1.2, 1.2), y = c(-1.2, 1.2))

My session info:

R version 3.6.0 (2019-04-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows Server x64 (build 17763)

Matrix products: default

locale:
[1] LC_COLLATE=Chinese (Simplified)_China.936 
[2] LC_CTYPE=Chinese (Simplified)_China.936   
[3] LC_MONETARY=Chinese (Simplified)_China.936
[4] LC_NUMERIC=C                              
[5] LC_TIME=Chinese (Simplified)_China.936    

attached base packages:
 [1] stats4    parallel  grid      stats     graphics  grDevices utils    
 [8] datasets  methods   base     

other attached packages:
 [1] shiny_1.4.0         progress_1.2.2      RColorBrewer_1.1-2 
 [4] igraph_1.2.4.2      ggraph_2.0.3        OmicsDP_1.10.0     
 [7] xcms_3.6.2          MSnbase_2.10.1      ProtGenerics_1.20.0
[10] S4Vectors_0.22.1    mzR_2.18.0          Rcpp_1.0.3         
[13] BiocParallel_1.18.1 Biobase_2.44.0      BiocGenerics_0.30.0
[16] impute_1.58.0       DMwR2_0.0.2         uuid_0.1-2         
[19] mailR_0.4.1         wkb_0.3-0           openssl_1.4.1      
[22] knitr_1.26          reshape2_1.4.3      RODBC_1.3-15       
[25] fs_1.3.1            xml2_1.2.2          yaml_2.2.0         
[28] jsonlite_1.6        data.table_1.12.8   pROC_1.16.1        
[31] randomForest_4.6-14 xgboost_0.90.0.2    ggrepel_0.8.1      
[34] gplots_3.0.1.1      ggbeeswarm_0.6.0    gridExtra_2.3      
[37] ggplotify_0.0.4     forcats_0.5.0       stringr_1.4.0      
[40] dplyr_1.0.0         purrr_0.3.3         readr_1.3.1        
[43] tidyr_1.0.0         tibble_3.0.1        ggplot2_3.2.1      
[46] tidyverse_1.3.0     magrittr_1.5       

loaded via a namespace (and not attached):
  [1] clipr_0.7.0            utf8_1.1.4             R.utils_2.9.2         
  [4] tidyselect_1.1.0       devtools_2.2.1         munsell_0.5.0         
  [7] codetools_0.2-16       preprocessCore_1.46.0  dials_0.0.6           
 [10] miniUI_0.1.1.1         withr_2.1.2            colorspace_1.4-1      
 [13] highr_0.8              rstudioapi_0.11        robustbase_0.93-5     
 [16] rJava_0.9-12           TTR_0.23-4             mzID_1.22.0           
 [19] labeling_0.3           polyclip_1.10-0        DiceDesign_1.8-1      
 [22] farver_2.0.1           rprojroot_1.3-2        vctrs_0.3.0           
 [25] generics_0.0.2         ipred_0.9-9            xfun_0.11             
 [28] R6_2.4.1               doParallel_1.0.15      graphlayouts_0.7.0    
 [31] bitops_1.0-6           lhs_1.0.2              gridGraphics_0.4-1    
 [34] assertthat_0.2.1       promises_1.1.0         scales_1.1.0          
 [37] nnet_7.3-12            beeswarm_0.2.3         gtable_0.3.0          
 [40] affy_1.62.0            processx_3.4.1         tidygraph_1.2.0       
 [43] timeDate_3043.102      rlang_0.4.6            workflows_0.1.1       
 [46] splines_3.6.0          lazyeval_0.2.2         ModelMetrics_1.2.2.1  
 [49] broom_0.5.6            BiocManager_1.30.10    modelr_0.1.6          
 [52] backports_1.1.5        httpuv_1.5.2           quantmod_0.4-15       
 [55] MassSpecWavelet_1.50.0 caret_6.0-85           usethis_1.5.1         
 [58] tools_3.6.0            lava_1.6.6             affyio_1.54.0         
 [61] ellipsis_0.3.0         sessioninfo_1.1.1      parsnip_0.1.1         
 [64] plyr_1.8.5             zlibbioc_1.30.0        ps_1.3.0              
 [67] prettyunits_1.0.2      rpart_4.1-15           viridis_0.5.1         
 [70] zoo_1.8-6              haven_2.2.0            reprex_0.3.0          
 [73] RANN_2.6.1             GPfit_1.0-8            pcaMethods_1.76.0     
 [76] whisker_0.4            packrat_0.5.0          pkgload_1.0.2         
 [79] xtable_1.8-4           mime_0.8               hms_0.5.2             
 [82] evaluate_0.14          XML_3.98-1.20          readxl_1.3.1          
 [85] IRanges_2.18.3         testthat_2.3.1         compiler_3.6.0        
 [88] KernSmooth_2.23-15     ncdf4_1.17             crayon_1.3.4          
 [91] R.oo_1.23.0            htmltools_0.4.0        later_1.0.0           
 [94] lubridate_1.7.4        DBI_1.1.0              tweenr_1.0.1          
 [97] dbplyr_1.4.2           MASS_7.3-51.4          Matrix_1.2-17         
[100] cli_2.0.2              vsn_3.52.0             R.methodsS3_1.7.1     
[103] gdata_2.18.0           gower_0.2.1            pkgconfig_2.0.3       
[106] rvcheck_0.1.6          sp_1.3-2               recipes_0.1.9         
[109] MALDIquant_1.19.3      foreach_1.4.7          vipor_0.4.5           
[112] multtest_2.40.0        prodlim_2019.11.13     rvest_0.3.5           
[115] callr_3.4.0            digest_0.6.23          rmarkdown_2.0         
[118] cellranger_1.1.0       curl_4.0               gtools_3.8.1          
[121] lifecycle_0.2.0        nlme_3.1-143           desc_1.2.0            
[124] viridisLite_0.3.0      askpass_1.1            limma_3.40.6          
[127] fansi_0.4.0            pillar_1.4.3           lattice_0.20-38       
[130] pkgbuild_1.0.6         fastmap_1.0.1          httr_1.4.1            
[133] DEoptimR_1.0-8         survival_2.44-1.1      remotes_2.1.0         
[136] glue_1.4.1             xts_0.11-2             iterators_1.0.12      
[139] ggforce_0.3.1          class_7.3-15           stringi_1.4.3         
[142] memoise_1.1.0          caTools_1.17.1.2 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions