Using for loops correctly - r

I have never used for loops before and I would like to use it for my data. However, I still don't know how to use it properly. Could anyone tell me how to use for loops correctly?
For item 1 to 9
the results I wanted to get
real<lower=0>l1_0+l1_11
real<lower=0>l2_0+l2_11
real<lower=0>l3_0+l3_11
..
real<lower=0>l9_0+l9_11
For item 10 to 18
real<lower=0>l10_0+l10_12
real<lower=0>l11_0+l11_12
real<lower=0>l12_0+l12_12
..
real<lower=18>l18_0+l18_12
What I tried to do..
for(i in 1:9){
i=l[i]"_0"+l[i]"_11"
print(paste("real<lower=0>",i))
}
for (i in 1:9){
i<-paste('l',i,'_0',sep='')
print(paste("real<lower=0>",i)
}

Assuming you have no background in programming and just want to know how to use the for loop. I have created a very simple data-frame and will do something easy.
I want to have the sum of each row in the data-frame (luckily we also have the apply family to do this simply).
df <- data.frame(x=c(1,4,2,6,7,1,8,9,1),
y=c(4,7,2,8,9,1,9,2,8))
This is the example shown everywhere, which is highly unsatisfactory.
for(i in 1:10){
print(i)
}
Only print the example of the sum of each row.
for(i in 1:nrow(df)){
print(df$x[i]+df$y[i])
}
This is the part often horrible explained everywhere (I do not get why? Perhaps I just used the wrong searching terms/keywords?). Fortunately, there was a good example here on Stack Exchange that showed me how. So, the credits go to someone else. Yet, this part is fairly easy, but for someone with no background in modeling, R, or any programming what so ever, it can be an pain in the ass to figure out. To make a for loop and store the results, you NEED to create an object that can store the data of the loop.
Here a simple for loop storing the results in a data frame.
loopdf <- as.data.frame(matrix(ncol = 1, nrow = 0))
for(i in 1:nrow(df)){
loopdf[i,] <- df$x[i]+df$y[i]
}
loopdf
Here a simple for loop storing the results in a list.
looplist <- list()
for(i in 1:nrow(df)){
looplist[[i]] <- df$x[i]+df$y[i]
}
do.call(rbind, looplist)
Here a loop concatenating the results in an atomic vector.
loopvec <- NULL
for(i in 1:nrow(df)){
loopvec <- c(loopvec, df$x[i]+df$y[i])
}
loopvec
Here the apply loop (two versions).
apply(df, 1, sum)
apply(df, 1, function(x), sum(x))

Related

How Can I Avoid This For Loop? (R)

I currently have a for loop as below and it does not run as fast as I would like it to.
library(dplyr)
DF<-data.frame(Name=c('Bob','Joe','Sally')) #etc
PrimaryResult <- Function1(DF)
ResultsDF<-Function2(PrimaryResult)
for(i in 1:9)
{
Filtered<-filter(DF,Name!=PrimaryResult[i,2])
NextResult <- Function1(Filtered)
ResultsDF<-rbind(ResultsDF,Function2(NextResult))
}
The code takes an initial result of Function1 (which is a list of names) and tries it again with each name in the initial result being excluded individually to provide alternative results. These are returned as a one row data frame via Function2 and appended to the Results data frame.
How can I make this faster?
It seems like your main problem is the appending results from function 2 each iteration with rbind. This is classically slow because you are telling R to rewrite a bunch of information at each time step and R does not really know how large of a vector you are going to end up with.
Try making your results into a list vector. I don't really know what your functions do so I can't really assist with that part.
results_list <- vector("list", 10)
results_list[[1]] <- Function2(PrimaryResult)
for(i in 1:9){
Filtered<-filter(DF,Name!=PrimaryResult[i,2])
NextResult <- Function1(Filtered)
results_list[[i+1]]<-rbind(results_list[[i]],Function2(NextResult))
}
This is not perfect, but it should speed things up a bit.

My for loop won't run in r

I can't get this for loop to run.
loopLength <- length(vector_X)
i <- 1
for (x in 1:loopLength)
vector_Y <- Frame_X$column_a == vector_X[i]
Frame_Y <- Frame_X[Vector_Y,]
Frame_A <- Frame_Y$column_b == vector_X[i]
Frame_Z <- Frame_Y[Frame_A,]
Vector_T <- Frame_Y$column_c == Frame_Z[1,2]
Frame_Z2 <- Frame_Y[Vector_T,]
returnSum1[i] <- sum(Frame_Z2$column_d)
Frame_Z3 <- Frame_Y[!(Frame_Z1),]
returnSum2[i] <- sum(Frame_X3$column_d)`
I can run the stand_alone code block by replacing the i with an integer (it is only running from 1 to 20) and crosscheck the db and the results are correct. However, I can't seem to iterate it.
I think I'm missing something glaring about integrating a loop but I've looked and can't seem to find it.
It doesn't work when I try to run it as for (i in 1:20) either.
Nor do the inclusion or exclusion around brackets around the code block work either.
The variable you defined in your for loop is named x, not i. If that isn't it, then the error might come from the fact that if Frame_Z happens to have 0 rows, then Frame_Z[1,2] doesn't exist! I think that step in particular is not very clear. I could help more if you posted an example data.frame and said what you want to do. Also, it would make your code easier to read if you used less steps and didn't name indices Frames (as in Frame_A and Frame_Z1). Also, I think using dplyr would be easier. Something like:
library(dplyr)
loopLength <- length(vector_X)
for(i in 1:loopLength){
xval <- vector_X[i]
Frame_Z <- Frame_X %>%
filter(column_a == xval, column_b == xval)
...
}
I can't post more because I don't quite get what you are trying to do though.

How to use extract function in a for loop?

I am using the extract function in a loop. See below.
for (i in 1:length(list_shp_Tanzania)){
LU_Mod2000<- extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj)
}
Where maj function is:
maj <- function(x){
y <- as.numeric(names(which.max(table(x))))
return(y)
}
I was expecting to get i outputs, but I get only one output once the loop is done. Somebody knows what I am doing wrong. Thanks.
One solution in this kind of situation is to create a list and then assign the result of each iteration to the corresponding element of the list:
LU_Mod2000 <- vector("list", length(list_shp_Tanzania))
for (i in 1:length(list_shp_Tanzania)){
LU_Mod2000[[i]] <- extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj)
}
Do not do
LU_Mod2000 <- c(LU_Mod2000, extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj))
inside the loop. This will create unnecessary copies and will take long to run. Use the list method, and after the loop, convert the list of results to the desired format (usually using do.call(LU_Mod2000, <some function>))
Alternatively, you could substitute the for loop with lapply, which is what many people seem to prefer
LU_Mod2000 <- lapply(list_shp_Tanzania, function(z) extract(x=rc_Mod2000_LC, y=z, fun=maj))

usings a for loop to append to an empty object in r

this may seem like a novice question, but I'm struggling to understand why this doesn't work.
answer = c()
for(i in 1:8){
answer = c()
knn.pred <- knn(data.frame(train_week$Lag2), data.frame(test_week$Lag2), train_week$Direction, k=i)
test <- mean(knn.pred == test_week$Direction)
append(answer, test)
}
I want the results 1-8 in a vector called answer. it should loop through 8 times, so ideally a vector with 8 numbers would be my output. When I run the for loop, I only get the final answer, meaning it isn't appending. any help would be appreciated, sorry for the novice question, really trying to learn R.
First of all, please include a reproducible example in your question next time. See How to make a great R reproducible example?.
Second, you set answer to c() in the first line of your loop, so this happens in each iteration.
Third, append, just like almost all functions in R, does not modify its argument in place, but it returns a new object. So the correct code is:
answer = c()
for (i in 1:8){
knn.pred <- knn(data.frame(train_week$Lag2), data.frame(test_week$Lag2),
train_week$Direction, k = i)
test <- mean(knn.pred == test_week$Direction)
answer <- append(answer, test)
}
While this wasn't the question, I can't help noting that this is a very inefficient way of creating vectors and lists. It is an anti-pattern. If you know the length of the result vector, then allocate it, and set its elements. E.g
answer = numeric(8)
for (i in 1:8){
knn.pred <- knn(data.frame(train_week$Lag2), data.frame(test_week$Lag2),
train_week$Direction, k = i)
test <- mean(knn.pred == test_week$Direction)
answer[i] <- test
}
You are overwriting answer inside the for loop. Try removing that line. Also, append doesn't act on its arguments directly; it returns the modified vector. So you need to assign it.
answer <- c()
for(i in 1:8){
knn.pred <- knn(data.frame(train_week$Lag2), data.frame(test_week$Lag2), train_week$Direction, k=i)
test <- mean(knn.pred == test_week$Direction)
answer <- append(answer, test)
}

How to get a loop not to overwrite the results?

I feel dumb asking such a simple question, but I can't seem to find a way, although I'm sure there are plenty of ways. The easiest way to explain my problem might be to show an example, I've got some program I want applied.
FUN<- function(v1, v2, v3){
n=length(v1)
res <- vector()
for (i in 1:n){
if(v1[i]>v2[i]) (res[i] <- v3[i+2])
else(res[i] <- v1[i+2])}
return(res)}
The input is two vectors and a matrix, all being the same length
matrix <- matrix(runif(30),ncol=3)
v2 <- runif(10)
v3 <- rnorm(10)
So that when I run the a for loop including the function I can do the program i times and each time the output goes to a different column in a matrix. I've tried something like and several similar "versions", but with no luck.
for (i in 1:3)(
r <- matrix()
r[re,i] <- re <- FUN(matrix[,i], v2, v3))
Can anyone please help me?
r <- matrix(ncol=3, nrow=10)
for (i in 1:3) {
r[,i] <- FUN(matrix[,i], v2, v3)
}
Declare your matrix outside the loop, and just fill in one column per loop iteration.
(This assumes that FUN is correct; even if it is, there are better ways to do what it does. And other ways to do what you want other than a loop.)

Resources