问题
I have this code:
library(networkD3)
# Load data
data(MisLinks)
data(MisNodes)
new.nodes <- MisNodes
new.nodes$var1 <- runif(nrow(MisNodes),1,2)
new.nodes$var2 <- runif(nrow(MisNodes),1,2)
# Some script to show the node index in the new.nodes data frame
script <- 'alert("row: " + (d.index + 1));'
# Plot
forceNetwork(Links = MisLinks, Nodes = new.nodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
Group = "group", opacity = 0.8,
clickAction = script)
I figured out to get the row number of the node data frame by asking for d.index + 1
. However I want to show a table containing all the node info, like so (perhaps nicer formatted):
name group size var1 var2
1 Myriel 1 15 1.501311 1.053062
This would require the JavaScript to have access to the node data frame, as I only have little knowledge of JavaScript I cannot figure out how to request this data.
回答1:
The reason this happens is that the forceNetwork
function strips out all the unnecessary variables/columns in the data frame that it passes to JavaScript, which is advantageous usually, but not in this case. You can work around it by saving the htmlwidget object that forceNetwork
creates, then add back in the variable you need to access, and then 'print'/display it.
library(networkD3)
data(MisLinks)
data(MisNodes)
MisNodes$var1 <- runif(nrow(MisNodes),1,2)
script <- 'alert("var1: " + (d.var1));'
fn <- forceNetwork(Links = MisLinks, Nodes = new.nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
Group = "group", opacity = 0.8, clickAction = script)
fn$x$nodes$var1 <- MisNodes$var1
fn
This could be done with/for multiple variables as well, for example...
library(networkD3)
data(MisLinks)
data(MisNodes)
MisNodes$var1 <- runif(nrow(MisNodes),1,2)
MisNodes$var2 <- runif(nrow(MisNodes),1,2)
script <- 'alert("var1: " + d.var1 + "\\n" + "var2: " + d.var2);'
fn <- forceNetwork(Links = MisLinks, Nodes = new.nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
Group = "group", opacity = 0.8, clickAction = script)
fn$x$nodes$var1 <- MisNodes$var1
fn$x$nodes$var2 <- MisNodes$var2
fn
回答2:
Unfortunately, I think it is not easily done if not impossible. It appears that only the used the arguments of forceNetwork
relating to the nodes are initialized in the underlying code:
Consider for example:
script <- 'alert("row: " + (d.index + 1) +
", name: " + d.name +
", group: " + d.group +
", size: " + d.nodesize +
", var1: " + d.var1)'
# Plot
d3 <- forceNetwork(Links = MisLinks, Nodes = new.nodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
Nodesize = "size",
Group = "group", opacity = 0.8,
clickAction = script)
print(d3)
As you can see when clicking a node below, the var1 is undefined. Note I added the Nodesize
argument to the function call which now can be accessed through the script d.nodesize
(and not d.size
). The group
variable and argument, in this case, are named identically so the distinction is lost here. However, the NodeID
is apparently accessed by the stated name which I find inconsistent.
You can see the generated source by saving:
saveNetwork(d3, file = "test.html")
You can notice by looking at it, that the values you intend to output are not stored in the file.
Edit:
By your own suggestion, this comes somewhat close as a workaround:
new.nodes$newname <- with(new.nodes, paste(", name: ", name, ", group: ", group,
", size: ", size, ", var1: ", var1,
", var2: ", var2))
newscript <- 'alert("row: " + (d.index + 1) + d.name)'
forceNetwork(Links = MisLinks, Nodes = new.nodes,
Source = "source", Target = "target",
Value = "value", NodeID = "newname", Nodesize = "size",
Group = "group", opacity = 0.8, opacityNoHover = 0,
clickAction = newscript)
So, it is just a matter of formatting the string as you'd like it displayed. The downside is that name/NodeIDs are very long. And as you can see, the NodeID is just always called name
on the JS side.
来源:https://stackoverflow.com/questions/52477969/r-networkd3-click-action-to-show-information-from-node-data-frame