rgraphpopupigraphvisnetwork

R: Display "popup" information when mouse hovers over (graph) visnetwork


I simulated some data and created a graph network in R using visnetwork:

library(igraph)
library(dplyr)
library(visNetwork)

#create file from which to sample from
x5 <- sample(1:100, 1100, replace=T)
#convert to data frame
x5 = as.data.frame(x5)

#create first file (take a random sample from the created file)
a = sample_n(x5, 1000)
#create second file (take a random sample from the created file)
b = sample_n(x5, 1000)

#combine
c = cbind(a,b)
#create dataframe
c = data.frame(c)
#rename column names
colnames(c) <- c("a","b")


#create graph
graph <- graph.data.frame(c, directed=F)
graph <- simplify(graph)


plot(graph)
fc <- fastgreedy.community(graph)
V(graph)$community <- fc$membership
library(visNetwork)
nodes <- data.frame(id = V(graph)$name, title = V(graph)$name, group = V(graph)$community)
nodes <- nodes[order(nodes$id, decreasing = F),]
edges <- get.data.frame(graph, what="edges")[1:2]

#visnet graph
visNetwork(nodes, edges) %>%   visIgraphLayout(layout = "layout_with_fr") %>%
    visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

Right now, the graph only displays node information when you click on it. Suppose if each node had observed properties in the "original file". E.g.

#add some information corresponding to the original data

other_damages_in_dollars <- rnorm(1000,104,9)

location <- c("canada","usa")

location <- sample(location, 1000, replace=TRUE, prob=c(0.3, 0.7))

type_of_house <- c("single","townhome", "rental" )

type_of_house<- sample(type_of_house , 1000, replace=TRUE, prob=c(0.5, 0.3, 0.2))

#heres how the original data would have looked like

original_data = data.frame(a,b, other_damages_in_dollars, location, type_of_house)

Is there a way to add this information when you click on each node?

 #visnet graph - is it possible to use the '$' operator to add these properties?

     visNetwork(nodes, edges) %>%   visIgraphLayout(layout = "layout_with_fr") %>%
        %>%    visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)visEvents(selectEdge = "function(properties) { alert(this.body.data.edges._data[properties.edges[0]].original_data$location); }")  %>%    visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)visEvents(selectEdge = "function(properties) { alert(this.body.data.edges._data[properties.edges[0]].original_data$type_of_house); }")  %>%    visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)visEvents(selectEdge = "function(properties) { alert(this.body.data.edges._data[properties.edges[0]].original_data$other_damage_in_dollars); }")

Solution

  • You don't need an event. This is built into many of the vis.js elements.

    So, I'll start with designing the content of my tooltip. Of the 1000 rows you made of location, home types, and costs, I created a subset with the same number of rows as there are nodes. This is what will be shown in my tooltip.

    newTitle = paste0("Location: ", toupper(location[1:nrow(nodes)]),
                      "<br>Home Type: ", type_of_house[1:nrow(nodes)],
                      "<br>Damage Related Costs: ", 
                      sprintf("$%.2f", other_damages_in_dollars[1:nrow(nodes)]))
    #check it; looks okay
    

    Now I'm going to make my tooltips the titles of my nodes.

    # replace the node titles:
    nodes$title = newTitle
    

    Call the network and click anywhere on the graph once to activate it. Now you just have to hover....(note the blue box, that means it's listening). There are a lot of nodes really close together, so there will be a bit of delayed response when you move from node to node.

    You can get rid of the need to click to activate with visOptions(clickToUse = F).

    visNetwork(nodes, edges) %>% visIgraphLayout(layout = "layout_with_fr") 
    

    enter image description here enter image description here

    enter image description here

    enter image description here

    enter image description here enter image description here

    FYI

    I didn't go through all of the code in the original question; there's a lot! I'm going to include what I ran before creating my graph, so you know what was in and what was not. This code is not changed from your question.

    library(igraph)
    library(dplyr)
    library(visNetwork)
    
    #create file from which to sample from
    x5 <- sample(1:100, 1100, replace=T)
    #convert to data frame
    x5 = as.data.frame(x5)
    
    #create first file (take a random sample from the created file)
    a = sample_n(x5, 1000)
    #create second file (take a random sample from the created file)
    b = sample_n(x5, 1000)
    
    #combine
    c = cbind(a,b)
    #create dataframe
    c = data.frame(c)
    #rename column names
    colnames(c) <- c("a","b")
    #create graph
    graph <- graph.data.frame(c, directed=F)
    graph <- simplify(graph)
    fc <- fastgreedy.community(graph)
    V(graph)$community <- fc$membership
    nodes <- data.frame(id = V(graph)$name, title = V(graph)$name, group = V(graph)$community)
    nodes <- nodes[order(nodes$id, decreasing = F),]
    edges <- get.data.frame(graph, what="edges")[1:2]
    
    #add some information corresponding to the original data
    other_damages_in_dollars <- rnorm(1000,104,9)
    location <- c("canada","usa")
    location <- sample(location, 1000, replace=TRUE, prob=c(0.3, 0.7))
    type_of_house <- c("single","townhome", "rental" )
    type_of_house<- sample(type_of_house , 1000, replace=TRUE, prob=c(0.5, 0.3, 0.2))
    
    #heres how the original data would have looked like
    original_data = data.frame(a,b, other_damages_in_dollars, location, type_of_house)