I have a list of letters l
[1] a b c
[2] b c a b
and a vector v of letter too
[1] a
[2] b
My object is to take the letters of the vector v one by one and creating a new list that contains all the letter appearing after that letter.
For example
I take the first letter of v "a" and I create the list of letter appearing after "a" , And I got this :
[1] b c
[2] b
After i take the second letter or v which is "b"
and I add to the list :
[3] c
[4] c a b
So the final result is :
[1] b c
[2] b
[3] c
[4] c a b
I don't know how to do this, it seems complicated.
I have also a list of vector with this format
[[1]]
[1] a
[2] b
[3] c
[[2]]
[1] e
[2] g
A nested lapply:
lapply(v, function(v, l) lapply(l, function(x, v) {
if (!(v %in% x)) return(x) #the case of no match
x[-seq_len(which.max(x == v))]
}, v = v), l = l)
#[[1]]
#[[1]][[1]]
#[1] "b" "c"
#
#[[1]][[2]]
#[1] "b"
#
#
#[[2]]
#[[2]][[1]]
#[1] "c"
#
#[[2]][[2]]
#[1] "c" "a" "b"
Here is one approach using lapply.
dat <- list( c("a", "b", "c"), c("b", "c", "a", "b"))
v <- c("a", "b")
result <- list()
for (l in v) {
result[[l]] <- lapply(dat, function(z) z[(which(z == l)[1] + 1):length(z)])
}
result
Related
I have a four atomic vectors that I want to use to create a named list of atomic vectors where the names of the list are based on the first two, and the content of these list elements are the last two vectors repeated for each of the two first vectors.
# Naming vectors
v1 <- c("a", "b", "c")
v2 <- c("g", "h", "i")
# Content vectors
a <- 1:5
b <- LETTERS[1:5]
# I want to add each of the vectors a and b as repeated list elements
# in list l and name the list element after vectors v1 and v2, respectively.
l <- list()
# Step 1: Adding vector 'a' to list
l <- lapply(v1, function(x) {
append(l, a) %>%
unlist()
})
# Step 2: Adding vector 'b' to list
l <- lapply(v2, function(x) {
append(l, b) %>%
unlist()
})
# Step 3: Naming vector
names(l) <- c(v1, v2)
l
# The desired output (not working)
$a
1 2 3 4 5
$b
1 2 3 4 5
$c
1 2 3 4 5
$g
'A' 'B' 'C' 'D' 'E'
$h
'A' 'B' 'C' 'D' 'E'
$i
'A' 'B' 'C' 'D' 'E'
The last sentence should have added names to the list, but it didn't work. Instead I get the error message:
Error in names(l) <- c(v1, v2): 'names' attribute [6] must be the same length as the vector [3]
Troubleshooting
Commenting out step 2 and removing 'v2' from step 3, I get the desired output:
# Step 1: Adding vector 'a' to list
> l <- lapply(v1, function(x) {
append(l, a) %>%
unlist()
})
> names(l) <- v1
> l
$a
1 2 3 4 5
$b
1 2 3 4 5
$c
1 2 3 4 5
Commenting out step 3 and adding step 2 returns
# Step 1: Adding vector 'a' to list
> l <- lapply(v1, function(x) {
append(l, a) %>%
unlist()
})
# Step 2: Adding vector 'b' to list
> l <- lapply(v2, function(x) {
append(l, b) %>%
unlist()
})
> l
1. '1''2''3''4''5''1''2''3''4''5''1''2''3''4''5''A''B''C''D''E'
2. '1''2''3''4''5''1''2''3''4''5''1''2''3''4''5''A''B''C''D''E'
3. '1''2''3''4''5''1''2''3''4''5''1''2''3''4''5''A''B''C''D''E'
For some reason, adding step 2 will append the output into the list elements created in step 1 instead of creating new ones, and the list elements in step 1 are repeated 3 times.
How can I append the second step's list elements names appropriately?
Is this what you are looking for?
# Naming vectors
v1 <- c("a", "b", "c")
v2 <- c("g", "h", "i")
# Content vectors
a <- 1:5
b <- LETTERS[1:5]
# Create lists of length v1/v2 and put in contents
v1_list <- lapply(v1, function(x) a)
v2_list <- lapply(v2, function(x) b)
# Combine the lists
l <- c(v1_list, v2_list)
#Rename
names(l) <- c(v1, v2)
l
#> $a
#> [1] 1 2 3 4 5
#>
#> $b
#> [1] 1 2 3 4 5
#>
#> $c
#> [1] 1 2 3 4 5
#>
#> $g
#> [1] "A" "B" "C" "D" "E"
#>
#> $h
#> [1] "A" "B" "C" "D" "E"
#>
#> $i
#> [1] "A" "B" "C" "D" "E"
Created on 2022-01-05 by the reprex package (v2.0.1)
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
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'm asking to how to merge two lists in parallel, not orderly append as below codes.
For example,
A <- list(c(1,2,3), c(3,4,5), c(6,7,8))
B <- list(c("a", "b", "c"), c("d", "e", "f"), c("g", "h", "i"))
As results,
[[1]]
[[1]][[1]]
[1] 1 2 3
[[1]][[2]]
[1] "a" "b" "c"
[[2]]
[[2]][[1]]
[1] 3 4 5
[[2]][[2]]
[1] "d" "e" "f"
[[3]]
[[3]][[1]]
[1] 6 7 8
[[3]][[2]]
[1] "g" "h" "i"
Using Map simply:
Map(list,A,B)
A longer approach (not recursive yet, up to second level merging):
A <- list(c(1,2,3), c(3,4,5), c(6,7,8))
B <- list(c("a", "b", "c"), c("d", "e", "f"), c("g", "h", "i"))
mergepar <- function(x = A, y = B) { # merge two lists in parallel
ln <- max(length(x), length(y)) # max length
newlist <- as.list(rep(NA, ln)) # empty list of max length
for (i in 1:ln) { # for1, across length
# two level subsetting (first with [ and then [[, so no subscript out of bound error) and lapply
newlist[[i]] <- lapply(list(A, B), function(x) "[["("["(x, i), 1))
}
return(newlist)
}
I have a list of vector :
[[1]]
[1] a
[2] f
[3] e
[4] a
[[2]]
[1] f
[2] f
[3] e
I would like to know if is there a way to transform it in a list (simple list of characters) like this :
[1] a f e a
[2] f f e
Thank you
You can use unlist
l1 <- list(list("a", "f", "e", "a"),
list("f", "f", "e"))
lapply(l1, unlist)
[[1]]
[1] "a" "f" "e" "a"
[[2]]
[1] "f" "f" "e"