R - Merge Two member lists of a list - r

I have list l of the form say :
R> l
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
Now, I want to merge to member lists of this list. For instance, when I say I want to merge l[[1]] and l[[2]], I want the result to be :
R> l
[[1]]
[1] 1 2
[[2]]
[1] 3
[[3]]
[1] 4
While merging two list, I don't need dupilcate elements in the result. Hence, I am using union over two member lists.
R> union(l[[1]], l,[[2]])
[1] 1 2
How can I do this merge operation? Can I do this using some predefined function?
Thanks

You can write you own merge as follows:
l <- as.list(1:4)
mymerge <- function(mylist, element1, element2){
mylist[[element1]] <- union(mylist[[element1]], mylist[[element2]])
mylist[[element2]] <- NULL
return(mylist)
}
l <- mymerge(l,1,2)
Result:
> l
[[1]]
[1] 1 2
[[2]]
[1] 3
[[3]]
[1] 4
Comment: As akrun pointed out, you can also use c instead of union

Related

Adding elements of combinations of vector in a list in R

I am pretty new in R and so what I am trying to do is that I have been given a vector of positive integers like
index <- 1:3
and I want to use this vector to find all the possible combinations of numbers without repetition which I achieve like this
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
print(t(combn(index,i))[j,])
j = j + 1
append(comb, j)
}
}
This gives me output as
[1] 1
[1] 2
[1] 3
[1] 1 2
[1] 1 3
[1] 2 3
[1] 1 2 3
But when I create a list comb <- list() and try to append each output as below:
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
append(comb, t(combn(index,i))[j,])
j = j + 1
}
}
The problem is it is giving my empty list when I call
comb
list()
I wish to create a list with those elements and use them to retrieve those index rows from a data frame. Do you have any idea how I can achieve this? Any help is welcome. Thanks!
We can use unlist + lapply like below
unlist(
lapply(
seq_along(index),
combn,
x = index,
simplify = FALSE
),
recursive = FALSE
)
which gives
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 1 2
[[5]]
[1] 1 3
[[6]]
[1] 2 3
[[7]]
[1] 1 2 3
This seems to give what you want
index <- 1:3
comb <- list()
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
comb <- c(comb, list(t(combn(index,i))[j,]))
j = j + 1
}
}
comb
Output
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 1 2
[[5]]
[1] 1 3
[[6]]
[1] 2 3
[[7]]
[1] 1 2 3
Note that you have to assign your appended list back. Also if you append a list with vector each of the vector element will be a separate element in the new list. You have to wrap that vector in a list() function to append it as one.

How to unlist nested lists while keeping vectors

I'd like to unlist a nested list with has some items as vectors. The problem is that unlist also splits up these vectors. How can I keep them as single items?
a) one level up (unlist parameter: recursive = F)
b) all levels (unlist parameter: recursive = T)
Here's the example:
list0 <- list(c(1,2),
list(3,
c(4,5)
)
)
> list0
[[1]]
[1] 1 2
[[2]]
[[2]][[1]]
[1] 3
[[2]][[2]]
[1] 4 5
If we unlist one level:
list1 <- unlist(list0, recursive = F)
we get:
> list1
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4 5
but, as I'd like to keep vectors as they are, I'd like to get:
[[1]]
[1] 1 2
[[2]]
[1] 3
[[3]]
[1] 4 5
Maybe one way is with a for loop, but I guess that would be slow if the number of lists is high.
Could anyone give me some hints, please?
Thanks in advance
For your example, the code below gives the expected result.
f <- function(x){
if(is.atomic(x)){
list(x)
}else{
x
}
}
unlist(lapply(list0, f), recursive=FALSE)
But perhaps you need something which works with more nested levels, like:
f <- function(x){
if(is.atomic(x)){
list(x)
}else{
x
}
}
g <- function(L){
out <- unlist(lapply(L, f), recursive=FALSE)
while(any(sapply(out, is.list))){
out <- g(out)
}
out
}
list1 <- list(c(1,2),
list(3, c(4,5)),
list(6, list(c(7,8)))
)
list1_flattened <- g(list1)
which gives:
> list1
[[1]]
[1] 1 2
[[2]]
[[2]][[1]]
[1] 3
[[2]][[2]]
[1] 4 5
[[3]]
[[3]][[1]]
[1] 6
[[3]][[2]]
[[3]][[2]][[1]]
[1] 7 8
> list1_flattened
[[1]]
[1] 1 2
[[2]]
[1] 3
[[3]]
[1] 4 5
[[4]]
[1] 6
[[5]]
[1] 7 8

R foreach and print behavior

I am noticing this behavior of foreach and print in R. foreach somehow repeats the elements, but assigning result to variable "rectify" it.
> for (i in 1:3) {print(i+1)}
[1] 2
[1] 3
[1] 4
> foreach (i=1:3) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
> x<-foreach (i=1:3) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
> x
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
> foreach (i=1:3, .combine=c) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
[1] 2 3 4
> foreach (i=1:3) %do% {(i+1)}
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
> x <-foreach (i=1:3) %do% {(i+1)}
> x
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
> x<-for (i in 1:3) {(i+1)}
> x
NULL
Moreover, that brings me to the last test with simple for. for loop does not output results while foreach does.
If I would want to pick up results from for clause, is there another dedicated way rather than
> x <- NULL
> for (i in 1:3) {x <- cbind(x,(i+1))}
> x
[,1] [,2] [,3]
[1,] 2 3 4
From the help page, ?foreach (emphasis added):
The foreach and %do%/%dopar% operators provide a looping construct that can be viewed as a hybrid of the standard for loop and lapply function. It looks similar to the for loop, and it evaluates an expression, rather than a function (as in lapply), but it's purpose is to return a value (a list, by default), rather than to cause side-effects.
Regarding, the link to lapply, which also returns a list, observe the analog to the above code:
lapply(1:3, print)
[1] 1
[1] 2
[1] 3
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
So the lapply loop prints each value in an iteration and then returns the input as a list in the same manner as foreach.

X value of each element in list

how do I get the x value of each element in the list.
example:
list1 <- list(1:3,4:6)
list1
#[[1]]
#[1] 1 2 3
#
#[[2]]
#[1] 4 5 6
Imaginary function I'm looking for:
function(list1, 1)
# [1] 1 4
function(list2, 2)
# [1] 2 5
How can I do this?
Use sapply or lapply, in combination with the [ extraction function (see ?Extract for more info) like so:
> sapply(list1,"[",1)
[1] 1 4
...or with a list output:
> lapply(list1,"[",1)
[[1]]
[1] 1
[[2]]
[1] 4

R list from variables using variable names [duplicate]

This question already has answers here:
Can lists be created that name themselves based on input object names?
(4 answers)
Closed 4 years ago.
I've looked extensively for a solution for this very simple task and though I have a solution, it seems like there must be a better way. The task is to create a list from a set of variables, using the variable names as names for each element in the list, e.g.:
a <- 2
b <- 'foo'
c <- 1:4
My current solution:
named.list <- function(...) {
l <- list(...)
names(l) <- sapply(substitute(list(...)), deparse)[-1]
l
}
named.list(a,b,c)
Produces:
$a
[1] 2
$b
[1] "foo"
$c
[1] 1 2 3 4
A couple of ways I can think of include mget (make assumptions about the environment your objects are located in):
mget( c("a","b","c") )
$a
[1] 2
$b
[1] "foo"
$c
[1] 1 2 3 4
Or as an edit to your function, you could use, match.call like this:
named.list <- function(...) {
l <- list(...)
names(l) <- as.character( match.call()[-1] )
l
}
named.list( a,b,c)
$a
[1] 2
$b
[1] "foo"
$c
[1] 1 2 3 4
Or you can do it in one go using setNames like this:
named.list <- function(...) {
l <- setNames( list(...) , as.character( match.call()[-1]) )
l
}
named.list( a,b,c)
$a
[1] 2
$b
[1] "foo"
$c
[1] 1 2 3 4
If you already using tidyverse packages, then you might be interested in using the tibble::lst function which does this
tibble::lst(a, b, c)
# $a
# [1] 2
#
# $b
# [1] "foo"
#
# $c
# [1] 1 2 3 4

Resources