I have data with 'from' and 'to' columns:
df = data.frame(from = c('A','A','X','E','B','W','C','Y'),
to = c('B','E','Y','C','A','X','A','W'))
I'd like to identify all sequences of 'from-to', considering two or more rows, which starts and ends on the same value. An easy one would be A-B-A:
# df
# from to
# 1 A B # 1. From A to B
# 2 A E
# 3 X Y
# 4 E C
# 5 B A # 2. From B and back to the starting point A, completing the sequence A-B-A
# 6 W X
# 7 C A
# 8 Y W
Another one:
# df
# from to
# 1 A B
# 2 A E # 1.
# 3 X Y
# 4 E C # 2.
# 5 B A
# 6 W X
# 7 C A # 3. -> Thus: A - E - C - A
# 8 Y W
There is also e.g. X - Y - W - X
How can I find such cycles?
Here is another option:
library(igraph)
g <- graph_from_data_frame(h)
#https://lists.nongnu.org/archive/html/igraph-help/2009-04/msg00125.html
find.cycles <- function(graph, k) {
ring <- graph.ring(k, TRUE)
subgraph_isomorphisms(ring, graph)
}
#find all cycles
N <- length(unique(unlist(h)))
l <- unlist(lapply(1L:N, find.cycles, graph=g), recursive=FALSE)
#extract the vertices in each cycle
Filter(Negate(is.null), lapply(l, function(e) {
if (length(e) > 1L) {
nm <- names(e)
c(nm, nm[1L])
}
}))
output:
[[1]]
[1] "A" "B" "A"
[[2]]
[1] "B" "A" "B"
[[3]]
[1] "A" "E" "C" "A"
[[4]]
[1] "X" "Y" "W" "X"
[[5]]
[1] "E" "C" "A" "E"
[[6]]
[1] "W" "X" "Y" "W"
[[7]]
[1] "C" "A" "E" "C"
[[8]]
[1] "Y" "W" "X" "Y"
Reference:
Re: [igraph] Help - find cycles by Gábor Csárdi
Related
I want to extract the names of the neighbors of selected nodes in igraph as a list.
This is what I have so far:
library(igraph)
set.seed(100)
g<-erdos.renyi.game(26, 0.4)
V(g)$name<-letters
x<-neighborhood(g, order = 1, V(g)$name %in% c('a', 'd', 'z'))
In the above example, I want to extract the names of the neighbours of nodes a,d, and z. And this is the output I am getting:
[[1]]
+ 9/26 vertices, named, from 6ba7060:
[1] a c h i l q w x z
[[2]]
+ 11/26 vertices, named, from 6ba7060:
[1] d b c e g h i k l w y
[[3]]
+ 9/26 vertices, named, from 6ba7060:
[1] z a c g h l o u v
I want to make a long list of the names with representations. The output should look like:
[1] "a" "c" "h" "i" "l" "q" "w" "x" "z" "d" "b" "c" "e" "g" "h" "i" "k" "l" "w" "y" "z" "a" "c"
[24] "g" "h" "l" "o" "u" "v
Thus far I have tried unlist and various versions of x %>% map(2) %>% flatten() using the library purrr, but to no avail.
I am also not oppose to getting the output in the form of a data.frame or tibble with names in one column and count of occurrences in another.
Maybe you can try names(unlist(x)), e.g.,
> names(unlist(x))
[1] "a" "c" "h" "i" "l" "q" "w" "x" "z" "d" "b" "c" "e" "g" "h" "i" "k" "l" "w"
[20] "y" "z" "a" "c" "g" "h" "l" "o" "u" "v"
You can apply names() to each elements in the list to get the vertex name as a character value, and then you can unlist those lists into a single character vector
unlist(lapply(x, names))
If you would rather a data frame with counts, you can do:
stack(table(unlist(lapply(x, names))))[2:1]
#> ind values
#> 1 a 2
#> 2 b 1
#> 3 c 3
#> 4 d 1
#> 5 e 1
#> 6 g 2
#> 7 h 3
#> 8 i 2
#> 9 k 1
#> 10 l 3
#> 11 o 1
#> 12 q 1
#> 13 u 1
#> 14 v 1
#> 15 w 2
#> 16 x 1
#> 17 y 1
#> 18 z 2
I have a list of vectors, j, that looks like this:
>j
[[1]
[1] "a" "b" "c"
[[2]]
[1] "c" "c"
[[3]]
[1] "d" "d" "d" "a" "a"
.
.
.
I would like to transform this into a dataframe that has one column with each vectors contents concatenated together. So the column would look like:
Column_Name
1 a b c
2 c c
3 d d d a a
I have tried using Replace() function as well as a loop where I would use after:
for (x in 1:length(j)){
j[x] = paste(j[x], collapse = " ")
}
j <- data.frame(matrix(unlist(j), nrow=length(j), byrow=T)
Any guidance would be greatly appreciated.
Thank you.
As you have tried yourself, the sapply function together with the collapse argument of paste should do it all wrapped into a data.frame:
# Toy data
set.seed(1)
j <- replicate(5, rep(sample(letters, 1), sample(1:10,1)))
print(j)
#[[1]]
#[1] "g" "g" "g" "g"
#
#[[2]]
# [1] "o" "o" "o" "o" "o" "o" "o" "o" "o" "o"
#
#[[3]]
#[1] "f" "f" "f" "f" "f" "f" "f" "f" "f"
#
#[[4]]
#[1] "y" "y" "y" "y" "y" "y" "y"
#
#[[5]]
#[1] "q"
# Collapse each element and wrap into a data.frame
res <- data.frame("Column_name" = sapply(j, paste, collapse = " "))
print(res)
# Column_name
#1 g g g g
#2 o o o o o o o o o o
#3 f f f f f f f f f
#4 y y y y y y y
#5 q
The sapply applies the paste-function on each element of the list to create a character vector of the concatenated list elements. The data.frame constructor simply converts that output to the wanted output.
Once provide the name to list and then use stack to convert list in a data.frame. Finally, dplyr package is used to collapse vector from common element separated by .
Sample Data is taken from #AndersEllernBilgrau's answer.
set.seed(1)
j <- replicate(5, rep(sample(letters, 1), sample(1:10,1)))
names(j) <- seq_along(j)
library(dplyr)
stack(j) %>% group_by(ind) %>%
summarise(Column_Name = paste0(values, collapse = " ")) %>%
ungroup() %>% select(-ind)
# # A tibble: 5 x 1
# Column_Name
# <chr>
# 1 g g g g
# 2 o o o o o o o o o o
# 3 f f f f f f f f f
# 4 y y y y y y y
# 5 q
#
I have 3 rows
first <- LETTERS[1:9]
second <- c(1:9)
third <- letters[1:9]
> first
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I"
> second
[1] 1 2 3 4 5 6 7 8 9
> third
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i"
I want the output vector of 9 elements with new line like that
"A "B
1 2
a" b" and so on
I try to use loop but it doesn't work
y <-c()
z <-c()
for(i in 1:length(first)){
y <- paste(first, second, sep = "\n")
z <- paste(y, third, sep = "\n")
}
I got out put
[1] "A\n1\na" "B\n2\nb" "C\n3\nc" "D\n4\nd"
[5] "E\n5\ne" "F\n6\nf" "G\n7\ng" "H\n8\nh"
[9] "I\n9\ni"
This is not give me a newline. The format of my colnames(data) for report need to be like that. Thanks for advance.
Am I understanding you correctly that you are looking for this:
first <- LETTERS[1:9]
second <- c(1:9)
third <- letters[1:9]
cat(c(first, "\n", second, "\n", third))
A B C D E F G H I
1 2 3 4 5 6 7 8 9
a b c d e f g h i
?
EDIT:
Will this solve your problem?
Printing R data frame with column names in multiple lines
I have 2 tables as below:
a = read.table(text=' a b
1 c
1 d
2 c
2 a
2 b
3 a
', head=T)
b = read.table(text=' a c
1 x i
2 y j
3 z k
', head=T)
And I want result to be like this:
1 x i c d
2 y j c a b
3 z k a
Originally I thought to use tapply to transform them to lists (eg. aa = tapply(a[,2], a[,1], function(x) paste(x,collapse=","))), then append it back to table b, but I got stuck...
Any suggestion to do this?
Thanks a million.
One way to do it:
mapply(FUN = c,
lapply(split(b, row.names(b)), function(x) as.character(unlist(x, use.names = FALSE))),
split(as.character(a$b), a$a),
SIMPLIFY = FALSE)
# $`1`
# [1] "x" "i" "c" "d"
#
# $`2`
# [1] "y" "j" "c" "a" "b"
#
# $`3`
# [1] "z" "k" "a"
I have 6 numeric lists each containing different number of values i.e [1:350] , [1:450] .... . I am trying to append all of these lists into a singular list i.e [1:1050] using rbind(), but the output I get is dataframe of [1:350, 1:6].
Can someone please help me with this.
To concatenate multiple lists, you can use c()
x <- list(1, 2:5)
y <- list("A", "B")
z <- list(letters[1:5])
c(x, y, z)
# [[1]]
# [1] 1
#
# [[2]]
# [1] 2 3 4 5
#
# [[3]]
# [1] "A"
#
# [[4]]
# [1] "B"
#
# [[5]]
# [1] "a" "b" "c" "d" "e"