Convert a graphNEL graph to a network graph - r

I'm trying to convert a graphNEL graph to network graph.
Here's my example using topGO's vignette:
library(topGO)
library(ALL)
data(ALL)
data(geneList)
affyLib <- paste(annotation(ALL),"db",sep= ".")
library(package=affyLib,character.only=TRUE)
topgo.obj <- new("topGOdata",description="Simple session",ontology="BP",allGenes=geneList,geneSel=topDiffGenes,nodeSize=10,annot=annFUN.db,affyLib=affyLib)
topgo.graph <- attr(topgo.obj,"graph")
And trying to convert topgo.graph to a network through intergraph
library(network)
library(sna)
library(scales)
library(igraph)
library(intergraph)
topgo.igraph <- graph_from_graphnel(topgo.graph,name=TRUE,weight=TRUE,unlist.attrs=TRUE)
And finally
topgo.network <- asNetwork(topgo.igraph,amap=attrmap())
throws this error:
Error in as.data.frame.default(x[[i]], optional = TRUE) :
cannot coerce class ""environment"" to a data.frame
When I try this with intergraph's example:
asNetwork(exIgraph)
it works fine
and as far I can tell exIgraph and topgo.igraph look similar:
> exIgraph
IGRAPH D--- 15 11 --
+ attr: label (v/c), label (e/c)
+ edges:
[1] 2-> 1 3-> 1 4-> 1 5-> 1 6-> 7 8-> 9 10->11 11->12 12->13 13->14 14->12
> topgo.igraph
IGRAPH DNW- 1017 2275 --
+ attr: name (v/c), genes (v/x), weight (e/n)
+ edges (vertex names):
[1] GO:0000003->GO:0008150 GO:0000070->GO:0000278 GO:0000070->GO:0007067 GO:0000070->GO:1903047 GO:0000070->GO:0000819
[6] GO:0000075->GO:0022402 GO:0000077->GO:0031570 GO:0000077->GO:0006974 GO:0000079->GO:1904029 GO:0000079->GO:0071900
[11] GO:0000082->GO:0044772 GO:0000082->GO:0044843 GO:0000086->GO:0000278 GO:0000086->GO:0044772 GO:0000086->GO:0044839
[16] GO:0000122->GO:0006357 GO:0000122->GO:0045892 GO:0000122->GO:0006366 GO:0000165->GO:0035556 GO:0000165->GO:0023014
[21] GO:0000187->GO:0032147 GO:0000187->GO:0043406 GO:0000209->GO:0016567 GO:0000226->GO:1902589 GO:0000226->GO:0007010
[26] GO:0000226->GO:0007017 GO:0000278->GO:0007049 GO:0000280->GO:0048285 GO:0000302->GO:0006979 GO:0000302->GO:1901700
[31] GO:0000723->GO:0006259 GO:0000723->GO:0032200 GO:0000723->GO:0060249 GO:0000819->GO:1902589 GO:0000819->GO:0098813
[36] GO:0000819->GO:0051276 GO:0000902->GO:0032989 GO:0000910->GO:0022402 GO:0000910->GO:0051301 GO:0001501->GO:0048731
+ ... omitted several edges
Any idea?

This is happening because of the "gene" attribute. If you view it using V(topgo.igraph)$gene, you will see it return a list of environments rather than a vector. When deep in the intergraph code, it tries to coerce the vertex attributes into a data frame, which it cannot do. (This happens in the dumpAttr() function -- see getAnywhere(dumpAttr.igraph).)
To solve this, you can simple delete the attribute:
topgo.igraph <- delete_vertex_attr(topgo.igraph,"genes")
topgo.network <- asNetwork(topgo.igraph,amap=attrmap())
The argument unlist.attrs=T I think is designed to prevent the exact problem above, but it is not working in this case. This might be due to the naming convention used by the genes in the network.
If you look at the attributes from the original graphNEL object, you will notice that it consists of objects of class environment:
> head(graph::nodeData(topgo.graph, attr = "genes"))
$`GO:0000003`
<environment: 0x15c005ae0>
$`GO:0000070`
<environment: 0x15c136bf0>
$`GO:0000075`
<environment: 0x15c118a70>
$`GO:0000077`
<environment: 0x15c13ae70>
$`GO:0000079`
<environment: 0x163145670>
$`GO:0000082`
<environment: 0x16313d148>)
You could also alter the attribute data in the original topGO object to solve the problem as well:
nodeData(topgo.graph, attr = "genes") <- topgo.obj#graph#nodes
topgo.igraph <- graph_from_graphnel(topgo.graph,name=TRUE,weight=TRUE,unlist.attrs=TRUE)
topgo.network <- asNetwork(topgo.igraph,amap=attrmap())
This preserves the genes a vertex attributes, if you want that:
> head(network::get.vertex.attribute(topgo.network, "genes"))
[1] "GO:0000003" "GO:0000070" "GO:0000075" "GO:0000077" "GO:0000079" "GO:0000082"

Related

How to make Ops method compatible between two objects of a non base class

Let's imagine that I have a class "my" and I want to trigger certain behaviour when it is added to an object that has units (i.e. from units package):
library(units)
my1 = structure(2, class="my")
Ops.my <- function(e1, e2=NULL) {
ok <-
switch(
.Generic,
`-` = ,
`*` = ,
`+` = ,
'<=' = TRUE,
FALSE
)
if (!ok) {
stop(gettextf("%s not meaningful", sQuote(.Generic)))
}
get(.Generic)(as.integer(e1), as.integer(e2))
}
my1+set_units(5,nm)
Currently, it gives me the following warning:
Warning message:
Incompatible methods ("Ops.my", "Ops.units") for "+"
But I actually want to handle "my" and "units" addition in a certain way, how do I do it?
I tried with something like Ops.my.units <- but it doesn't seem to work.
There doesn't seem to be a way to do this with Ops. From the docs:
The classes of both arguments are considered in dispatching any member of this group. For each argument its vector of classes is examined to see if there is a matching specific (preferred) or Ops method. If a method is found for just one argument or the same method is found for both, it is used. If different methods are found, there is a warning about ‘incompatible methods’
This is probably a good thing. Part of the benefit of an object-oriented system in a non-compiled language like R is that it helps preserve type safety. This stops you from accidentally adding apples to oranges, as we can see in the following example:
apples <- structure(2, class = "apples")
oranges <- structure(2, class = "oranges")
Ops.apples <- function(e1, e2) {
value <- do.call(.Generic, list(as.integer(e1), as.integer(e2)))
class(value) <- "apples"
value
}
Ops.oranges <- function(e1, e2) {
value <- do.call(.Generic, list(as.integer(e1), as.integer(e2)))
class(value) <- "oranges"
value
}
apples + apples
#> [1] 4
#> attr(,"class")
#> [1] "apples"
oranges + oranges
#> [1] 4
#> attr(,"class")
#> [1] "oranges"
apples + oranges
#> [1] 4
#> attr(,"class")
#> [1] "apples"
#> Warning message:
#> Incompatible methods ("Ops.apples", "Ops.oranges") for "+"
You can see that even here, we could just ignore the warning.
suppressWarnings(apples + oranges)
#> [1] 4
#> attr(,"class")
#> [1] "apples"
But hopefully you can see why this may not be good - we have added 2 apples and 2 oranges, and have returned 4 apples.
Throughout R and its extension packages, there are numerous type-conversion functions such as as.integer, as.numeric, as.logical, as.character, as.difftime etc. These allow for some element of control when converting between types and performing operations on different types.
The "right" way to do this kind of thing is specifically convert one of the object types to the other in order to perform the operation:
as.my <- function(x) UseMethod("as.my")
as.my.default <- function(x) {
value <- as.integer(x)
class(value) <- 'my'
value
}
my1 + as.my(set_units(5,nm))
#> [1] 7

Trouble With Outputting all Elements to Console

I have an issue where I'm trying to use sink() to capture my console output to a text file. However, my console keeps on restricting my print statements, despite having set max.print to the maximum integer in R.
I have consulted various other stackoverflow links but to no avail. Has anyone solved this issue?
This is a sample output, despite having changed max.print.
options(max.print = .Machine$integer.max)
> print(outputFile[1])
[[1]]
+ 1681/519133 vertices, named, from 71aeda5:
[1] p_8945206-t_25 p_24353782-t_0 p_5096967-t_0
[4] p_12728438-t_2 p_1914103-t_8 p_7949965-t_59
[7] p_5171435-t_4 p_6628106-t_7 p_2535537-t_0
[10] p_45026190-t_2 p_25504870-t_8 p_796238-t_1
[13] p_135998-t_13 p_20853906-t_1 p_17154085-t_0
[16] p_29505258-t_4 p_27269129-t_13 p_6793896-t_92
[19] p_5331193-t_1 p_11521441-t_2 p_34271996-t_2
[22] p_95594-t_0 p_16395989-t_0 p_582576-t_3
[25] p_9368888-t_1 p_697462-t_28 p_80124-t_72
[28] p_7595644-t_0 p_14372110-t_4 p_2083314-t_2
+ ... omitted several vertices
Additionally, I have tried indexing but it hasn't worked.
igraph specific options like auto.print.lines should still affect the printing of your graph objects, even if they're contained in a list. Using a combination of auto.print.lines and max.print, I'm able to get graphs to print out in full:
library(purrr)
library(igraph)
# Using purrr to create a list of multiple large graphs
gs = map(1:5, ~ random.graph.game(200, 0.1))
options(max.print = .Machine$integer.max)
igraph_options(auto.print.lines = Inf)
print(gs)

How to remove elements of a list in R?

I have an igraph object, what I have created with the igraph library. This object is a list. Some of the components of this list have a length of 2. I would like to remove all of these ones.
IGRAPH clustering walktrap, groups: 114, mod: 0.79
+ groups:
$`1`
[1] "OTU0041" "OTU0016" "OTU0062"
[4] "OTU1362" "UniRef90_A0A075FHQ0" "UniRef90_A0A075FSE2"
[7] "UniRef90_A0A075FTT8" "UniRef90_A0A075FYU2" "UniRef90_A0A075G543"
[10] "UniRef90_A0A075G6B2" "UniRef90_A0A075GIL8" "UniRef90_A0A075GR85"
[13] "UniRef90_A0A075H910" "UniRef90_A0A075HTF5" "UniRef90_A0A075IFG0"
[16] "UniRef90_A0A0C1R539" "UniRef90_A0A0C1R6X4" "UniRef90_A0A0C1R985"
[19] "UniRef90_A0A0C1RCN7" "UniRef90_A0A0C1RE67" "UniRef90_A0A0C1RFI5"
[22] "UniRef90_A0A0C1RFN8" "UniRef90_A0A0C1RGE0" "UniRef90_A0A0C1RGX0"
[25] "UniRef90_A0A0C1RHM1" "UniRef90_A0A0C1RHR5" "UniRef90_A0A0C1RHZ4"
+ ... omitted several groups/vertices
For example, this one :
> a[[91]]
[1] "OTU0099" "UniRef90_UPI0005B28A7E"
I tried this but it does not work :
a[lapply(a,length)>2]
Any help?
Since you didn't provide any reproducible data or example, I had to produce some dummy data:
# create dummy data
a <- list(x = 1, y = 1:4, z = 1:2)
# remove elements in list with lengths greater than 2:
a[which(lapply(a, length) > 2)] <- NULL
In case you wanted to remove the items with lengths exactly equal to 2 (question is unclear), then last line should be replaced by:
a[which(lapply(a, length) == 2)] <- NULL

How to create igraph mult-graph list

I have a number of networks, currently represented as edgelists, and I can create individual igraph objects from them:
> nodes <- read.csv("nodes.csv",header=T,as.is=T)
> links <- read.csv("edges.csv",header=T,as.is=T)
> net <- graph_from_data_frame(d=links, vertices=nodes, directed=T)
> net
IGRAPH f40255d DNW- 255 458 --
+ attr: name (v/c), word (v/c), type (e/c), weight (e/n)
+ edges from f40255d (vertex names):
[1] s001->s002 s001->s004 s001->s006 s001->s013 s001->s018 s001->s020
[7] s001->s025 s001->s027 s001->s031 s001->s032 s001->s033 s001->s034
[13] s001->s035 s001->s037 s001->s038 s001->s041 s001->s042 s001->s044
[19] s001->s046 s001->s047 s001->s050 s001->s051 s001->s052 s001->s055
[25] s001->s059 s001->s060 s001->s064 s001->s065 s001->s067 s001->s068
[31] s001->s069 s001->s070 s001->s072 s001->s074 s001->s075 s001->s078
[37] s001->s081 s001->s088 s001->s091 s001->s092 s001->s093 s001->s098
[43] s001->s100 s001->s103 s001->s111 s001->s112 s001->s112 s001->s118
+ ... omitted several edges
But I want to analyze I want to analyze these using the graphkernels package in R, which requires a list of igraph graphs. I have looked over the docs but I can't find any guidance on how to turn a number of these into a list. Can anyone point me in the right direction?
Sorry if this is a dumb question. I am minimally proficient in R.
Update: I tried creating 3 igraph objects and putting them in a list with
g <- list(net1,net2,net3)
But when I try to run this I get
> result <- CalculateWLKernel(g,5)
Error in CalculateKernelCpp(graph.info.list, par, 11) :
vector::_M_default_append
In addition: There were 12 warnings (use warnings() to see them)
So obviously something isn't right.

extract vertex from a R graph

I have the following problem.
A directed graph called tutti
I have a vector called tabellaerrori containing a vertex in each position
Now my problem is:
I want to create an array cointaining the list of vertex which are both in tutti graph and in errori vector.
I used the following code but it doesn't work:
risultato<-as.character(intersect(tabellaerrori,V(tutti)))
It gives me back always the content of tabellaerrori
What's wrong ?
For those who didn't suffer through the non-downloadable google plus image gallery, the actual line generating the error is:
graph.neighborhood(tutti, vcount(tutti), risultato, "out")
## Error in as.igraph.vs(graph, nodes) : Invalid vertex names
From the help - graph.neighborhood(graph, order, nodes=V(graph), mode=c("all", "out", "in")) is expecting nodes to be an actual igraph vertex sequence. You just need to make sure your intersected nodes are in that form.
Here's what jbaums meant by a reproducible example (provided I've made the right assumptions from your screen captures):
library(igraph)
set.seed(1492) # makes this more reproducible
# simulate your overall graph
tutti <- graph.full(604, directed=TRUE)
V(tutti)$name <- as.character(sample(5000, 604))
# simulate your nodes
tabellaerrori <- as.character(c(sample(V(tutti), 79), sample(6000:6500, 70)))
names(tabellaerrori) <- as.numeric(tabellaerrori)
# give a brief view of the overall data objects
head(V(tutti))
## Vertex sequence:
## [1] "1389" "1081" "922" "553" "261" "42"
length(V(tutti))
## [1] 604
head(tabellaerrori)
## 293 415 132 299 408 526
## "293" "415" "132" "299" "408" "526"
length(tabellaerrori)
## [1] 149
# for your answer, find the intersection of the vertext *names*
risultato <- as.character(intersect(tabellaerrori, V(tutti)$name))
risultato
## Vertex sequence:
## [1] "293" "132" "155" "261" "68" "381" "217" "394" "581"
# who are the ppl in your neighborhood
graph.neighborhood(tutti, vcount(tutti), risultato, "out")
## [[1]]
## IGRAPH DN-- 604 364212 -- Full graph
## + attr: name (g/c), loops (g/l), name (v/c)
##
## [[2]]
## IGRAPH DN-- 604 364212 -- Full graph
## + attr: name (g/c), loops (g/l), name (v/c)
##
## ... (a few more)
What you were really doing before (i.e. what intersect was doing under the covers) is:
risultato <- as.character(intersect(tabellaerrori, as.character(V(tutti))))
hence, your Invalid vertex names error.

Resources