Reputation: 99
I've been trying to plot a network using networkD3 package in R for a week now. The simpleNetwork
function works normally, but it doesn't allow much control over the appearance of the graph. The forceNetwork
function is there for this purpose: display graph with enriched visual features.
The problem I have is pretty much the same exposed in this question. I have carefully read the package documentation, and tried the solution proposed in the above thread, with no luck: all I get is a cloud of nodes with no edges linking them.
Here my data.frame
s:
edg
Gene1 Gene2 Prob
1 22 3
2 22 6
3 22 6
4 22 9
5 22 3
6 22 4
7 22 8
8 22 4
9 22 6
10 22 8
11 22 6
12 22 10
13 22 6
14 22 3
15 22 6
16 22 6
17 22 0
18 22 4
19 22 6
20 22 4
vert
Symbol Chr Expr
1 21 9
2 17 10
3 17 0
4 20 0
5 6 9
6 5 11
7 12 0
8 1 20
9 17 11
10 17 7
11 17 11
12 10 0
13 17 0
14 7 7
15 17 6
16 17 0
17 2 5
18 5 10
19 17 10
20 17 9
21 12 4
22 3 2
Well, this results in the above mentioned cloud of nodes with no edges. Same thing if I change 'Symbol' column with actual labels I'd put on the nodes (respecting the order of Links' table, as required by the package).
Note that the package illustrates the use of this function with this example, and if you open the datsets used (MisLinks, MisNodes), their content is the same as mine, except for the labels of the nodes. Running that very same example works; running with my data does not.
Here is the function I use to plot the network:
forceNetwork( Links = edg, Nodes = vert, Source = "Gene1", Target = "Gene2",
Value = "Prob", NodeID = "Symbol", Group = "Chr", opacity = 0.7,
colourScale = "d3.scale.category20b()", Nodesize = "Expr", zoom = T,
legend = T )
Every other property is correctly displayed (node size, legend, colours), but I keep seeing no edges. There must be a mistake somewhere in my datasets, which I cannot find in any way.
Upvotes: 3
Views: 3686
Reputation: 1
I met the same problem, but fixed it by setting the factor levels of source and target to be consistent with node names before transferring into numeric:
edg$Gene1<-factor(edg$Gene1,levels=vert$Symbol)
edg$Gene2<-factor(edg$Gene2,levels=vert$Symbol)
edg$source<-as.numeric(edg$Gene1)-1
edg$target<-as.numeric(edg$Gene2)-1
so that source and target vectors have consistent factor levels as node names (vert$Symbol
), then
forceNetwork( Links = edg, Nodes = vert, Source = "source", Target = "target",
Value = "Prob", NodeID = "Symbol", Group = "Chr", opacity = 0.7,
colourScale = "d3.scale.category20b()", Nodesize = "Expr", zoom = T,
legend = T )
works for me.
Hope this is helpful.
Upvotes: 0
Reputation: 8848
Technically speaking, the reason your example data will not work, even if you address other possible problems (like edg$Gene1
and edg$Gene2
being non-numeric), is because you refer to a node 22
in your edg
data, which in "0-based index" terms points to the 23rd row of your vert
data frame, which does not exist.
As has been pointed out, this is probably because it is in 1-based indexing and should be converted, which could easily be done with
edg$Gene1 <- edg$Gene1 - 1
edg$Gene2 <- edg$Gene2 - 1
Alternatively, one might have intended to refer to another node which, for whatever reason did not make it into the vert
data frame, in which case that node would need to be added to the vert
data frame, which could easily be done with (for example)...
vert <- rbind(vert, c(23,1,1))
You could test whether or not you refer to a node in your edj
data that doesn't exist in your vert
data with something like...
all(unique(c(edg$Gene1, edg$Gene2)) %in% (1:nrow(vert) - 1))
# [1] FALSE
which should return TRUE
. If not, something's wrong.
You could determine which nodes are referred to in your edg
data that do not exist in your vert
data with...
unique(c(edg$Gene1, edg$Gene2))[which(!unique(c(edg$Gene1, edg$Gene2)) %in% (1:nrow(vert) - 1))]
# [1] 22
fully reproducible example adjusting the indices in edg
to be "0-based"
edg <- read.csv(header = TRUE, colClasses = 'character', text = '
Gene1,Gene2,Prob
1,22,3
2,22,6
3,22,6
4,22,9
5,22,3
6,22,4
7,22,8
8,22,4
9,22,6
10,22,8
11,22,6
12,22,10
13,22,6
14,22,3
15,22,6
16,22,6
17,22,0
18,22,4
19,22,6
20,22,4
')
vert <- read.csv(header = TRUE, colClasses = 'character', text = '
Symbol,Chr,Expr
1,21,9
2,17,10
3,17,0
4,20,0
5,6,9
6,5,11
7,12,0
8,1,20
9,17,11
10,17,7
11,17,11
12,10,0
13,17,0
14,7,7
15,17,6
16,17,0
17,2,5
18,5,10
19,17,10
20,17,9
21,12,4
22,3,2
')
# cast to numeric just to be sure
edg$Gene1 <- as.numeric(edg$Gene1)
edg$Gene2 <- as.numeric(edg$Gene2)
# adjust the indices so they're "0-based"
edg$Gene1 <- edg$Gene1 - 1
edg$Gene2 <- edg$Gene2 - 1
# Nodesize is also necessarily numeric
vert$Expr <- as.numeric(vert$Expr)
library(networkD3)
forceNetwork(Links = edg, Nodes = vert, Source = "Gene1", Target = "Gene2",
Value = "Prob", NodeID = "Symbol", Group = "Chr", opacity = 0.7,
Nodesize = "Expr", zoom = TRUE, legend = TRUE)
fully reproducible example adding a node to vert
edg <- read.csv(header = TRUE, colClasses = 'character', text = '
Gene1,Gene2,Prob
1,22,3
2,22,6
3,22,6
4,22,9
5,22,3
6,22,4
7,22,8
8,22,4
9,22,6
10,22,8
11,22,6
12,22,10
13,22,6
14,22,3
15,22,6
16,22,6
17,22,0
18,22,4
19,22,6
20,22,4
')
vert <- read.csv(header = TRUE, colClasses = 'character', text = '
Symbol,Chr,Expr
1,21,9
2,17,10
3,17,0
4,20,0
5,6,9
6,5,11
7,12,0
8,1,20
9,17,11
10,17,7
11,17,11
12,10,0
13,17,0
14,7,7
15,17,6
16,17,0
17,2,5
18,5,10
19,17,10
20,17,9
21,12,4
22,3,2
')
# cast to numeric just to be sure
edg$Gene1 <- as.numeric(edg$Gene1)
edg$Gene2 <- as.numeric(edg$Gene2)
vert$Expr <- as.numeric(vert$Expr)
# add another node to the Nodes data frame
vert <- rbind(vert, c(23,1,1))
library(networkD3)
forceNetwork(Links = edg, Nodes = vert, Source = "Gene1", Target = "Gene2",
Value = "Prob", NodeID = "Symbol", Group = "Chr", opacity = 0.7,
Nodesize = "Expr", zoom = TRUE, legend = TRUE)
Upvotes: 0
Reputation: 51
I was having the same problem (simpleNetwork
working normally, forceNetwork
first displaying only nodes & no edges, then subsequently no display at all).
The problem (which you presumably fixed when you "rebuilt dataframes starting numbering from 0") was your original Links data, edg, starting from 1 instead of 0?
The networkD3 documentation, http://christophergandrud.github.io/networkD3/, has this note:
Note: You are probably used to R’s 1-based numbering (i.e. counting in R starts from 1). However, networkD3 plots are created using JavaScript, which is 0-based. So, your data links will need to start from 0.
Re. incorrect data types which I also originally thought might be the problem, I tested casting all the different columns (except the factor variable for the NodeID) as.numeric
vs as.integer
- however having now corrected my data to be 0-based instead of 1-based, my forceNetwork
display works normally with either data type.
Hope this helps!
Upvotes: 5
Reputation: 193
I have just fixed the same problem in my own forceNetwork. It turned out that the dataframe of edges that I had created (exported from iGraph) had character
types, not int
types. Casting the edge 'from' and 'to' columns using as.numeric()
resolved the problem and the links drew correctly.
I hope this helps.
With regards,
Will
Upvotes: 2