s__
s__

Reputation: 9485

R: how to make a networkD3 network reactive to subsetting of the data

I'm working with the networkD3 package, and I'm unable to make some sub-networks with my data.

I have a dataset made in this way (MisNodes and MisLinks are provided by the package itself):

library(networkD3)

data("MisNodes")
head(MisNodes)
#              name group size
# 1          Myriel     1   15
# 2        Napoleon     1   20
# 3 Mlle.Baptistine     1   23
# 4    Mme.Magloire     1   30
# 5    CountessdeLo     1   11
# 6        Geborand     1    9

data("MisLinks")
head(MisLinks)
#   source target value
# 1      1      0     1
# 2      2      0     8
# 3      3      0    10
# 4      3      2     6
# 5      4      0     1
# 6      5      0     1

The full network is this:

forceNetwork(
  Links  = MisLinks, Nodes   = MisNodes,
  Source = "source", Target  = "target",
  Value  = "value",  NodeID  = "name",
  Group  = "group",  opacity = 1)

enter image description here

Now, I'd like to select one of the group, and see only the nodes of that group, and the links that have as source the nodes in that group:

So I tried this:

# here the group
k <-c(1)

# add id, to subset well
MisNodes$id <- rownames(MisNodes)

# select the desired nodes
nodes <- (MisNodes[MisNodes$group %in% k,])

# select the links that have as source the desired nodes
links <- (MisLinks[rownames(MisLinks) %in% nodes$id,])   

# rownames from 0 
rownames(nodes) <- 1:nrow(nodes)-1 

# indexing from 0 to max
links$source_ <-match(links$source, sort(unique(links$source)))-1
links$target_ <-match(links$target, sort(unique(links$target)))-1

But the result is not correct, due that alone point should be linked to the central node.

enter image description here

Looking at the links:

links
   source target value source_ target_
1       1      0     1       0       0
2       2      0     8       1       0
3       3      0    10       2       0
4       3      2     6       2       1
5       4      0     1       3       0
6       5      0     1       4       0
7       6      0     1       5       0
8       7      0     1       6       0
9       8      0     2       7       0
10      9      0     1       8       0

Seems that the sources start from 1, but target from 0, but removing the -1, it works for the first group, but not from the others. Also the total using k <-c(1,2,3,4,5,6,7,8,9,10) is not correct. How could I make the network reactive correctly to subset of the data?

Upvotes: 1

Views: 418

Answers (1)

CJ Yetman
CJ Yetman

Reputation: 8848

The node ids use 0-based indexing, and you should also remove links that have a target node that is not in the group, otherwise you might have links to target nodes that don't exist in your nodes data (doesn't happen in group 1, but does in other groups).

library(networkD3)

data("MisNodes")
data("MisLinks")

group <- 1

nodes <- MisNodes

# record the original id (0-based index of the node in the data)
nodes$original_id <- 0:(nrow(MisNodes) - 1)

# trim the nodes to only those in the desired group
nodes <- nodes[nodes$group == group, ]


links <- MisLinks

# trim the links to only those that have a source and target node
# within the desired group
links <- links[links$source %in% nodes$original_id & 
                 links$target %in% nodes$original_id, ]

# match the node ids in the links data to the original id of the nodes
# and reset it to the current 0-based index of the nodes
links$source <- match(links$source, nodes$original_id) - 1
links$target <- match(links$target, nodes$original_id) - 1

forceNetwork(links, nodes,
             Source = "source", Target  = "target",
             Value  = "value",  NodeID  = "name",
             Group  = "group",  opacity = 1)

enter image description here

Upvotes: 3

Related Questions