Iteratively add to sequence in for loop R - r

I would like to iteratively add elements to a list over which I loop:
list = as.list(c(1,2,3))
list
for (x in list) {
new_element = as.list(x^2)
print(new_element)
list = union(list, new_element)
}
list
However, R takes only the original 3 elements in the loop.
I would like that the loop continues with the new elements. Any ideas on how I could adjust my code? Thanks!

Use a while loop rather than a for loop, together with break to eventually terminate:
mylist = as.list(c(1,2,3))
i <- 1
while(TRUE){
x <- mylist[[i]]
if(x<10){
new_element <- as.list(x^2)
print(new_element)
mylist = union(mylist, new_element)
i <- i+1
} else {
break
}
}
This causes mylist to have 7 items (lists containing 1,2,3,4,9,16,81 respectively) when the loop terminates.

Related

Tracking parent list in nested list

I have a nested loop that I need to iterate over. I want to go to the end of the list (in this case second item of the parent list), and add item to it if it isn't nested loop anymore. So loop may have many levels of nested loop. Right now, I'm only getting second list as a return. How do I track parent list?
a <- list( x = list(1,2,3),y =list(4,5,6))
con=TRUE
while(con){
i <-length(a)
for(k in i:i){
if(!typeof(a[[k]])=="list"){
a[[k+1]] <- "test"
con=FALSE
}else{
a <- a[[k]]
i <- length(a)
}
}
}
Expected Result:a <- list(x = list(1,2,3), y =list(4,5,6, "test"))
Result: a <- list(4,5,6,"test")
library(magrittr)
a <- list( x = list(1,2,3),y =list(4,5,6), z = 1)
temp <- lapply(a, typeof) %>% unlist
tempList <- (temp!="list")
if (sum(tempList) > 0) {
a[[max(which(tempList == FALSE))]] %<>% append("test")
} else {
a[[length(a)]] %<>% append("test")
}
It isn't clear to me what it is that you want to do, but
just concentrating on your example, this would work.
In short, see which elements of the parent list are not Lists, and for the last one of them add "test". If all of them are lists, then add "test" to the last one.

R - Saving the values from a For loop in a vector or list

I'm trying to save each iteration of this for loop in a vector.
for (i in 1:177) {
a <- geomean(er1$CW[1:i])
}
Basically, I have a list of 177 values and I'd like the script to find the cumulative geometric mean of the list going one by one. Right now it will only give me the final value, it won't save each loop iteration as a separate value in a list or vector.
The reason your code does not work is that the object ais overwritten in each iteration. The following code for instance does what precisely what you desire:
a <- c()
for(i in 1:177){
a[i] <- geomean(er1$CW[1:i])
}
Alternatively, this would work as well:
for(i in 1:177){
if(i != 1){
a <- rbind(a, geomean(er1$CW[1:i]))
}
if(i == 1){
a <- geomean(er1$CW[1:i])
}
}
I started down a similar path with rbind as #nate_edwinton did, but couldn't figure it out. I did however come up with something effective. Hmmmm, geo_mean. Cool. Coerce back to a list.
MyNums <- data.frame(x=(1:177))
a <- data.frame(x=integer())
for(i in 1:177){
a[i,1] <- geomean(MyNums$x[1:i])
}
a<-as.list(a)
you can try to define the variable that can save the result first
b <- c()
for (i in 1:177) {
a <- geomean(er1$CW[1:i])
b <- c(b,a)
}

For loops giving different results on console when run within a function in R

Hokay, so I have a for loop right at the end of this function here that's supposed to output the generated prime numbers that are created early in the function.
When I run the code line by line, everything works as expected and the two for loops output every element in the lists: PrimeList_p, PrimeList_q, to the console window.
When I run the code by calling the function however, the for loops only output the first 20 or so elements to the console. Why doesn't it print the whole list?
require(gmp)
GenPrimes <- function(InitialSize) {
#List initialisation
PrimeList_p <<- list()
PrimeList_q <<- list()
#Loop initialisation
x <- 1
#LOOP START
while (x < 81) {
#Generate and compile prime numbers into Prime_List1.
PrimeList_p[[x]] <- nextprime(urand.bigz(size = InitialSize + x, seed =
Sys.time()))
x <- x+1
PrimeList_q[[x]] <- nextprime(urand.bigz(size = InitialSize + x, seed =
Sys.time()))
x <- x+1
}
#LOOP END
#Remove NULL entries in lists
PrimeList_p <<- PrimeList_p[-which(sapply(PrimeList_p, is.null))]
PrimeList_q <<- PrimeList_q[-which(sapply(PrimeList_q, is.null))]
cat("Prime p:")
for (i in 1:40){
message(PrimeList_p[[i]])
}
cat("Prime q")
for (j in 1:40){
message(PrimeList_q[[j]])
}
}
GenPrimes(1)
You're incrementing x twice in a single loop. This creates NULL entries in both lists which is handled with code, but then saved to the parent environment. The original lists with NULL values still present in the function environment are then passed to the message loops which is why you see a blank line between each value. Change for (i in 1:40) to for (i in seq_along(PrimeList_p)) and this will become evident

use of double brackets unclear

I'm new to R. Reading Book Of R by Tilman Davies. An example is provided for how to use an externally defined helper function which incidentally utilizes double square brackets [[]]. Please explain what helper.call[[1]] and helper.call[[2]] are doing and use of double brackets here.
multiples_helper_ext <- function(x=foo,matrix.flags,mat=diag(2){
indexes <- which(matrix.flags)
counter <- 0
result <- list()
for(i in indexes){
temp <- x[[i]]
if(ncol(temp)==nrow(mat)){
counter <- counter+1
result[[counter]] <- temp%*%mat
}
}
return(list(result,counter))
}
multiples4 <- function(x,mat=diag(2),str1="no valid matrices",str2=str1){
matrix.flags <- sapply(x,FUN=is.matrix)
if(!any(matrix.flags)){
return(str1)
}
helper.call <- multiples_helper_ext(x,matrix.flags,mat=diag(2)
result <- helper.call[[1]] #I dont understand this use of double bracket
counter <- helper.call[[2]] #and here either
if(counter==0){
return(str2)
} else {
return(result)
}
}
foo <- list(matrix(1:4,2,2),"not a matrix","definitely not a matrix",matrix(1:8,2,4),matrix(1:8,4,2))
In R there are two basic types of objects: lists and vectors. The items of lists can be other objects, the items of of vectors are usually numbers, strings, etc.
To access items in a list, you use the double bracket [[]]. This gives back the object at that place of the list.
So
x <- 1:10
x is now a vector of integers
L <- list( x, x, "hello" )
L is a list whose first item is the vector x, its second item is the vector x, and its third item is the string "hello".
L[[2]]
This give back a vector, 1:10, which is stored in the 2nd place in L.
L[2]
This is a bit confusing, but this gives back a list whose only item is 1:10, i.e. it only contains L[[2]].
In R, when you want to return multiple values, you usually do this with a list. So, you might end you function with
f <- function() {
return( list( result1="hello", result2=1:10) )
}
x = f()
Now you can access the two results with
print( x[["result1"]] )
print( x[["result2"]] )
You can also access items of a list with ''$, so instead you can write
print( x$result1 )
print( x$result2 )
The syntax [[]] is used for list in python. Your helper.call is a list (of result and counter), so helper.cal[[1]] returns the first element of this list (result).
Have a look here: Understanding list indexing and bracket conventions in R

R return a conditioned number of objects in a FUNCTION

I have a function in which I want to return a different object per column of a matrix. However, I don't know how to make the return such that it identifies how many variables to create within a list given that it will be conditioned to the number of columns of the input matrix. In other words, how do I change the last command in the following function:
f <- function(Treat) {
for (i in c(1:ncol(Treat))) {
assign(paste0("Treat",i), as.matrix(Treat[,i]))
}
return(dat = list(Treat1=Treat1 , Treat2=Treat2, .....Treatn=Treatn))
}
lapply is what you are looking for
f <- function(Treat){
lapply(1:ncol(Treat), function(i) as.matrix(Treat[,i]))
}
lappy works nicely here. But you could also do it with an explicit loop (as per your original example) that assigns to a (pre-initialised) list as it goes:
empty_list <- list() # inititalise an empty list
f <- function(Treat, empty_list) { # set up the function
for (i in c(1:ncol(Treat))) { # set up the loop
empty_list[[i]] <- as.matrix(Treat[,i])) # write each column to a new element
}
return(empty_list) # return the list
}
You could then use this with:
full_list <- f(Treat, empty_list)

Resources