Recursive looping in r - r

I am new in R but I want to loop through elements of a given list recursively, to be presice I have alist of vectors where the first vector is given by (1,2,3,4), then I now want to loop through this vector and append the second vector obtained to the original list, again loop thorugh second vector in the list and get the third vector which is also appended on the original list and so on. I have this code to start with`
occlist <- list()
occ_cell <- c(1,2,3,4)
for(i in occ_cell){
occ_cell <- seq(i,4*i, by = 1)
occlist[[i]] <- occ_cell
}
`
gives the following list
#[[1]]
#[1] 1 2 3 4
#[[2]]
#[1] 2 3 4 5 6 7 8
#[[3]]
# [1] 3 4 5 6 7 8 9 10 11 12
#[[4]]
# [1] 4 5 6 7 8 9 10 11 12 13 14 15 16
I think to be more clear, lets have the following figure

recOcc <- function(i) {
if (i == 0) return ( NULL )
append( recOcc(i-1), list(seq(i, 4*i)) )
}
And, call with (to reproduce your output)
recOcc(4)
# [[1]]
# [1] 1 2 3 4
#
# [[2]]
# [1] 2 3 4 5 6 7 8
#
# [[3]]
# [1] 3 4 5 6 7 8 9 10 11 12
#
# [[4]]
# [1] 4 5 6 7 8 9 10 11 12 13 14 15 16
You can also use Recall to name your recursive function in the recursive call, which allows for the function name to change.
Edit
For the tree structure, you could try this
## i is the number to start the sequence
## depth determines how deep to recurse
recOcc2 <- function(i, depth=3, cur.depth=0) {
if (depth==cur.depth) return(seq(i, 4*i))
acc <- as.list(seq(i, 4*i))
for (ii in seq_along(acc))
acc[[ii]] <- recOcc2(acc[[ii]], depth, cur.depth+1)
acc
}
## To recreate the simple list
res <- recOcc2(1, depth=1)
## For nested lists
res <- recOcc2(1, depth=2)

Related

Get object and indices from subsetting call

Basically, I would like to create an R function separate_call that gets an argument like x[ind] and returns x and ind (so, from the parent environment):
x <- 1:10
ind <- 2:3
separate_call(x[ind]) ## should return `list(1:10, 2:3)`
I know that I need to use non-standard evaluation and some tree parsing but I'm not familiar enough with these two concepts. Any help would be appreciated.
Looking at the code of pryr:::tree and experimenting a little bit, I found a solution:
separate_call <- function(call) {
call.sep <- as.list(substitute(call))
parent_env <- parent.frame()
x <- eval(call.sep[[2]], parent_env)
ind <- eval(call.sep[[3]], parent_env)
list(x, ind)
}
Verification:
> x <- 1:10
> ind <- 2:3
> separate_call(x[ind])
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] 2 3
> separate_call(x[1:2])
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] 1 2
I am adding this solution, not very elegant, see if this fits your need.
separate_call <- function(m){
dprse <- deparse(substitute(m)) ##deparsing the data: to make it as string
lyst <- strsplit(dprse,"\\[|\\]")[[1]] ##removing the square brackets to sparate contents of m
lapply(lyst, function(y)eval(parse(text = y), envir = parent.frame()))
}
I hope this works, I tried it by calling it in three different ways
separate_call(1:10[ind])
separate_call(x[2:3])
separate_call(1:10[2:3])
They all gave me same response
> separate_call(1:10[ind])
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] 2 3
> separate_call(x[2:3])
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] 2 3
> separate_call(1:10[2:3])
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] 2 3

How can I add vector elements to corresponding vectors in lists?

I have a vectors of variable length in lists and a vector, somewhat like this:
set.seed(0)
x <- lapply(as.list(sample(1:10, 10, repl=TRUE)),
function(x) sample(1:10, x, repl=TRUE))
y <- sample(1:10, 10, repl=TRUE)
I need to add each element of y to a corresponding vector in x. Currently I accomplish this as so:
newList <- list()
for (i in seq_along(y)) {
newList <- c(newList, list(y[i] + x[[i]]))
}
> x[1:2]
[[1]]
[1] 1 3 2 7 4 8 5 8 10
[[2]]
[1] 4 8 10
> y[1:2]
[1] 4 8
> newList
[[1]]
[1] 5 7 6 11 8 12 9 12 14
[[2]]
[1] 12 16 18
[[3]]
[1] 13 17 12 13
...
Is there a better way, perhaps using a lapply-like function?
This is very similar to previous questions, which use Map or mapply to operate on two lists/vectors of the same length in tandem:
How do I apply an index vector over a list of vectors?
Add respective dataframes in list together in R
For this specific case, try:
Map("+",x,y)
#[[1]]
#[1] 5 7 6 11 8 12 9 12 14
#
#[[2]]
#[1] 12 16 18
#
#[[3]]
#[1] 13 17 12 13

mapply and two lists

I'm trying to use mapply to combine two lists (A and B). Each element is a dataframe.
I'm trying to rbind the dataframes in A to the corresponding dataframes in B. The following returns what I would like in combo1:
num = 10
A<-list()
B<-list()
for (j in 1:num){
A[[j]] <- as.data.frame(matrix(seq(1:9),3,3))
B[[j]] <- as.data.frame(matrix(seq(10:18),3,3))
}
combo1<-list()
for (i in 1:num){
combo1[[i]] <-rbind(A[[i]], B[[i]])
}
I'm trying to use mapply to do the same, but I can't get it to work:
combo2<-list()
combo2<-mapply("rbind", A, B)
I was hoping someone could please help me
You were very close!
## Make this a more _minimal_ reproducible example
A <- A[1:2]
B <- B[1:2]
## Override default attempt to reduce results to a vector, matrix, or other array
mapply("rbind", A, B, SIMPLIFY=FALSE)
# [[1]]
# V1 V2 V3
# 1 1 4 7
# 2 2 5 8
# 3 3 6 9
# 4 1 4 7
# 5 2 5 8
# 6 3 6 9
#
# [[2]]
# V1 V2 V3
# 1 1 4 7
# 2 2 5 8
# 3 3 6 9
# 4 1 4 7
# 5 2 5 8
# 6 3 6 9

Loop through a vector of vectors

When I loop through a vector of vectors, the result of each loop is several vectors. I would expect the result of each loop to be a vector. Please see the following example:
foo <- seq(from=1, to=5, by=1)
bar <- seq(from=6, to=10, by=1)
baz <- seq(from=11, to=15, by=1)
vects <- c(foo,bar,baz)
for(v in vects) {print(v)}
# [1] 1
# [1] 2
# [1] 3
# [1] 4
# [1] 5
# [1] 6
# [1] 7
# [1] 8
# [1] 9
# [1] 10
# [1] 11
# [1] 12
# [1] 13
# [1] 14
# [1] 15
This is odd as I would expect three vectors given it (should) iterate three times given the vector, c(foo,bar,baz). Something like:
# [1] 1 2 3 4 5
# [1] 6 7 8 9 10
# [1] 11 12 13 14 15
Can anyone explain why I am getting this result (15 vectors) and how to achieve the result I am looking for (3 vectors)?
Look at what vects is:
> vects
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
The c() joins (in this case) the three vectors, concatenating them into a single vector. In the for() loop, v takes on each values in vects in turn and prints it, hence the result you see.
Did you want a list of the three separate vectors? If so
> vects2 <- list(foo, bar, baz)
> for(v in vects2) {print(v)}
[1] 1 2 3 4 5
[1] 6 7 8 9 10
[1] 11 12 13 14 15
In other words, form a list of the vectors, not a combination of the vectors.
Substitute vects <- list(foo,bar,baz) for vects <- c(foo,bar,baz).
There is no such thing (really) as a vector of vectors.

Splitting a vector into two

How can I split a vector into two such that it selects a random sample for each new vector. But I always want to split in half. For instance
x <- 1:10
obj <- splitMyVector(x)
obj$a
> 5 3 9 7 10
obj$b
> 8 4 1 6 2
Note: the purpose for this is to do a split half reliability.
split(sample(x),letters[seq(length(x))%%2+1])
$a
[1] 9 7 10 4 2
$b
[1] 6 1 8 3 5

Resources