R foreach and print behavior - r

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.

Related

Print function in map behaves differently than in for loop in R

I am just practicing basic for loops to compare against their purrr::map() equivalent. However I am lost why the simple print function appears to double the output vs. its equivalent for loop.
#this simple for loop behaves as expected and gives us the numbers 1 through 10.
.x <- 1:10
for (i in .x){
print(i)
}
#result
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
#this doubles the output in an embedded list - I don't understand why
map(.x=.x,~print(.x))
#results below
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
[[5]]
[1] 5
[[6]]
[1] 6
[[7]]
[1] 7
[[8]]
[1] 8
[[9]]
[1] 9
[[10]]
[1] 10
I would have though they would produce the same (however I know the map results would be in a list unless I specify the output (eg. map_chr or map_df).
According to R documentations print prints its argument and returns it invisibly (via invisible(x)).
So your map function is essentially doing
.x <- 1:10
funcy <- function() {
out = list()
for (i in .x){
out[[i]] = print(i)
}
return(out)
}
funcy()
The print function gets called every loop and when the loop ends the function returns the stored values in a list
The purrr library has a function specifically designed for tasks such as this: walk.
If you don't want to return anything and are only calling functions for the purpose of their downstream effects (print or write_csv), you can use walk instead of map.
walk(1:10, print)
# [1] 1
# [1] 2
# [1] 3
# [1] 4
# [1] 5
# [1] 6
# [1] 7
# [1] 8
# [1] 9
# [1] 10

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

removing values from each element in a list in R

I was wondering if somebody could help with this problem. I have a list coming out from a function similar to the following:
lis<-vector("list",3)
lis[[1]]<-c(1,2,3)
lis[[2]]<-c(1,2,3)
lis[[3]]<-c(1,2,3)
so it looks like
[[1]]
[1] 1 2 3
[[2]]
[1] 1 2 3
[[3]]
[1] 1 2 3
What I want to do is remove, for example, the first element from each component of the list so it ends up like:
[[1]]
[1] 2 3
[[2]]
[1] 2 3
[[3]]
[1] 2 3
Any ideas would be most welcome.
You can use lapply() and do the index function for each element of the list. The index -1 means without the first element:
lis <- list(a=1:3, b=11:13, c=21:23)
lapply(lis, '[', -1)
# $a
# [1] 2 3
#
# $b
# [1] 12 13
#
# $c
# [1] 22 23

R - Merge Two member lists of a list

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

adding a field to each element of a list

I have a list
> (mylist <- list(list(a=1),list(a=2),list(a=3)))
[[1]]
[[1]]$a
[1] 1
[[2]]
[[2]]$a
[1] 2
[[3]]
[[3]]$a
[1] 3
and I want to add field b to each sublist from 11:13 to get something like
> (mylist <- list(list(a=1,b=11),list(a=2,b=12),list(a=3,b=13)))
[[1]]
[[1]]$a
[1] 1
[[1]]$b
[1] 11
[[2]]
[[2]]$a
[1] 2
[[2]]$b
[1] 12
[[3]]
[[3]]$a
[1] 3
[[3]]$b
[1] 13
How do I do this?
(note that I have a large number of such relatively small lists, so this will be called in apply and has to be reasonably fast).
mylist <- list(list(a=1),list(a=2),list(a=3))
b.vals <- 11:13
mylist <- lapply(
1:length(mylist),
function(x) {
mylist[[x]]$b <- b.vals[[x]]
mylist[[x]]
} )

Resources