Search code examples
rgraphlabeldata-visualizationigraph

Adding Labels to Graph Nodes


I made the following graph using the "visnetwork" library:

library(tidyverse)
library(igraph)


set.seed(123)
n=15
data = data.frame(tibble(d = paste(1:n)))

relations = data.frame(tibble(
  from = sample(data$d),
  to = lead(from, default=from[1]),
))

data$name = c("new york", "chicago", "los angeles", "orlando", "houston", "seattle", "washington", "baltimore", "atlanta", "las vegas", "oakland", "phoenix", "kansas", "miami", "newark" )

graph = graph_from_data_frame(relations, directed=T, vertices = data) 


 #red circle: starting point and final point
V(graph)$color <- ifelse(data$d == relations$from[1], "red", "orange")

plot(graph, layout=layout.circle, edge.arrow.size = 0.2, main = "my_graph")

library(visNetwork)

    a = visIgraph(graph)  

m_1 = 1
m_2 = 23.6

 a = toVisNetworkData(graph) %>%
    c(., list(main = paste0("Trip ", m_1, " : "), submain = paste0 (m_2, "KM") )) %>%
    do.call(visNetwork, .) %>%
    visIgraphLayout(layout = "layout_in_circle") %>% 
    visEdges(arrows = 'to') 
  • I am now trying to add number labels to each individual node, based on the order that they appear in (i.e. "red circle" is always 1, follow the arrow until you get to 2, etc.):

I tried to add an extra column to the data file to include these numbers (each "number label" corresponds to the order that the cities are visited in):

#is there an "automatic" way to do this? i did this manually:
data$label = c(11, 5, 2, 12, 7, 6, 10, 14, 15, 4, 12, 9, 13, 3,1)

I then tried to add both "number labels" and "name labels" (i.e. city) to the nodes in the visnetwork graph:

V(graph)$name = data$label = c(11, 5, 2, 12, 7, 6, 10, 14, 15, 4, 12, 9, 13, 3,1)

plot(graph, layout=layout.circle, edge.arrow.size = 0.2, main = "my_graph")

library(visNetwork)

    a = visIgraph(graph)  

m_1 = 1
m_2 = 23.6

 a = toVisNetworkData(graph) %>%
    c(., list(main = paste0("Trip ", m_1, " : "), submain = paste0 (m_2, "KM") )) %>%
    do.call(visNetwork, .) %>%
    visIgraphLayout(layout = "layout_in_circle") %>% 
    visEdges(arrows = 'to') 

a

But it gives me an error:

Error in `.rowNamesDF<-`(x, value = value) : 
  duplicate 'row.names' are not allowed
In addition: Warning message:
non-unique value when setting 'row.names': ‘12’ 

In the end, I would still like to make this graph (using visnetwork):

Is there another way to do this?

Thank you!


Solution

  • The reason for the error is that there is no 8 and there are 2 12s.

    sort(c(11, 5, 2, 12, 7, 6, 10, 14, 15, 4, 12, 9, 13, 3, 1))
    # [1]  1  2  3  4  5  6  7  9 10 11 12 12 13 14 15
    # missing 8, two 12
    

    To get the order dynamically-- (this uses the first a object you created in your code above)

    library(tidyverse)
    
    # collect the correct order
    
    df2 <- data %>% 
      mutate(d = as.numeric(d),
             nuname = factor(a$x$edges$from, 
                             levels = unlist(data$name))) %>%
      arrange(nuname) %>% 
      select(d) %>% unlist(use.names = F)
    #  [1] 11  5  2  8  7  6 10 14 15  4 12  9 13  3  1 
    

    If you set the labels as you've written the code here, you're overwriting the labels you currently have.

    There are a few options: keep as it is, combine the labels, or something you know that I don't know.

    Using these values and your code:

    V(graph)$name = data$label = df2
    

    Gives you:

    enter image description here

    To combine the labels, you could:

    V(graph)$name = data$label = paste0(df2, "\n", data$name)
    

    This gives you:

    enter image description here