I have some graph data stored in a data.table that describe the transitions between some nodes such as:
lfs = data.table( from = c(NA, 'x', 'x', 'y'), to = c('x', 'y', 'p', 'z'), level = 0)
lfs
# from to level
#: NA x 0
#: x y 0
#: x p 0
#: y z 0
I want to find the distance of each node from the start node NA
. The expected result is as follows:
# from to level
#: NA x 1
#: x y 2
#: x p 2
#: y z 3
I can solve this problem in a very cumbersome way as follows:
lfs[ is.na(lfs$from) ]$level = 1
target = lfs$from %in% (lfs[ lfs$level == 1 ]$to)
lfs[target]$level = 2
target = lfs$from %in% (lfs[ lfs$level == 2 ]$to)
lfs[target]$level = 3
I guess there should be easier and more generic solutions most probably by using graph manipulation functions in graph libraries such as igraph but I don't know them very well and I don't know what to search for in these libraries specifically.
How can I get the expected output using graph algorithms or do you think of any other easier solutions?
You can use the igraph
package to calculate the distances
library(igraph)
lfs = data.frame( from = c('start', 'x', 'x', 'y'),
to = c('x', 'y', 'p', 'z'),
level = 0)
# create graph from data.frame
g <- graph_from_data_frame(lfs)
# find distances from chosen node
distances(g, "start")
# start x y p z
#start 0 1 2 2 3
If we assume that each unique value in from
is already present in a previous row in column to
(except "start"
) - and the data is ordered the way you describe it - we could simply convert the form
column to numeric to attain the expected output.
lfs$level <- as.numeric(as.factor(lfs$from))
> lfs
# from to level
#1 start x 1 first 'from' value cannot be NA though
#2 x y 2
#3 x p 2
#4 y z 3
We can use rleid
from data.table
library(data.table)
lfs[, levels := rleid(from)]
lfs
# from to level levels
#1: NA x 0 1
#2: x y 0 2
#3: x p 0 2
#4: y z 0 3
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.