问题
I am trying to create a data set of network neighbors for a list of nodes. I though I could do this with an lapply function where I use the neighbors command. As an added complication, some of my lookup nodes aren't in the graph, but I can't get it to work regardless.
Here is an example:
edgelist <- read.table(text = "
A B
B C
C D
D E
C F
F G")
testlist <- read.table(text = "
A
H
C
D
J")
testlist2 <- read.table(text = "
A
C
B
D
E")
library(igraph)
graph <- graph.data.frame(edgelist)
str(graph)
neighbors<- lapply(testlist2, function(p) { #Each pledge_id
temp=neighbors(graph,p) #Find all the neighbors for that pledge
return(temp)
})
neighbors<- lapply(testlist, function(p) { #Each pledge_id
temp=neighbors(graph,p) #Find all the neighbors for that pledge
return(temp)
})
Unfortunately, this returns hogwash in both cases. What am I missing?
My desired output would be something like this:
lookupnode neighbor
A B
H .
C D
C F
D E
J .
I know eventually I need to add a temp=data.table::rbindlist(temp) command in somewhere, but I don't think that is causing the hogwash.
回答1:
One thing is that you're creating a data.frame with the read.table functions and passing in that data.frame to lapply so it's iterating over the each vector, not the elements of the V1 vector in the data.frame.
Second, that V1 column is a factor (h/t to @Psidom for the factor hint).
Third, the neighbors() function is going to return graph vertices which (from my reckoning) need to be iterated over and have the name attribute returned.
Then, as you suggest, these need to be rbinded into a data.frame:
get_neighbors <- function(graph, n) {
do.call(rbind, lapply(n, function(x) {
if (x %in% V(graph)$name) {
nb <- neighbors(graph, x)
if (length(nb) > 0) {
data.frame(lookupnode=x,
neighbor=nb$name, # h/t @MrFlick for this shortcut
stringsAsFactors=FALSE)
} else {
data.frame(lookupnode=x, neighbor=NA, stringsAsFactors=FALSE)
}
} else {
data.frame(lookupnode=x, neighbor=NA, stringsAsFactors=FALSE)
}
}))
}
get_neighbors(graph, as.character(testlist$V1))
## lookupnode neighbor
## 1 A B
## 2 H <NA>
## 3 C D
## 4 C F
## 5 D E
## 6 J <NA>
get_neighbors(graph, as.character(testlist2$V1))
## lookupnode neighbor
## 1 A B
## 2 C D
## 3 C F
## 4 B C
## 5 D E
## 6 E <NA>
I wonder if Gabor can vectorize neighbors() on the C-side.
UPDATE:
The ego solution is only a tad different:
get_ego <- function(g, v, n=2) {
do.call(rbind, lapply(v, function(x) {
if (x %in% V(g)$name) {
data.frame(node=x,
ego_n=sapply(ego(g, n, x), function(y) { V(g)[y]$name }),
stringsAsFactors=FALSE)
} else {
data.frame(node=x, ego_n=NA, stringsAsFactors=FALSE)
}
}))
}
来源:https://stackoverflow.com/questions/38645671/lapply-function-to-look-up-neighbors-in-igraph-when-not-all-nodes-are-found