stats_noob
stats_noob

Reputation: 5907

R: Saving the Results of a Loop

I am using the R programming language. I am learning about loops and how to store the results of a loop. For instance, I wrote the following code that loops a function (generates random data and fits different decision trees):

#load libraries    
    library(caret)
library(rpart)

#generate data

a = rnorm(1000, 10, 10)

b = rnorm(1000, 10, 5)

c = rnorm(1000, 5, 10)

group <- sample( LETTERS[1:2], 1000, replace=TRUE, prob=c(0.5,0.5) )
group_1 <- 1:1000

#put data into a frame
d = data.frame(a,b,c, group, group_1)

d$group = as.factor(d$group)

#place results in table
#final_table = matrix(1, nrow = 10, ncol=10)


e <- d



vec1 <- sample(200:300, 5)
vec2 <- sample(400:500,5)
vec3 <- sample(700:800,5)

for (i in seq_along(vec1)) { 
    for (j in seq_along(vec2)) {
        for (k in seq_along(vec3)) {
            # d <- e
            d$group_2 = as.integer(ifelse(d$group_1 < vec1[i] , 0, ifelse(d$group_1 >vec1[i]  & d$group_1 < vec2[j] , 1, ifelse(d$group_1 >vec2[j]  & d$group_1 < vec3[k] , 2,3))))
            
            
            
            
            d$group_2 = as.factor(d$group_2)
            
            fitControl <- trainControl(## 10-fold CV
                method = "repeatedcv",
                number = 2,
                ## repeated ten times
                repeats = 1)
            
            TreeFit <- train(group_2 ~ ., data = d[,-5],
                             method = "rpart",
                             trControl = fitControl)
            
            pred <- predict(
                TreeFit,
                d[,-5])
            
            con <- confusionMatrix(
                d$group_2,
                pred) 
            
            #update results into table
            #final_table[i,j] = con$overall[1]
            acc=c(vec1[i],vec2[j],vec3[k],con$overall[1])
            print(acc)
            
            
        }
    }
}

I am interested in saving the results of "acc" into a table (or a data frame). I am able to print all values of "acc", but when I formally view the results of "acc" : only the last line is displayed.

My question: is it possible to take the entire printed output (i.e. "acc") and store it into a table?

Thanks

Upvotes: 1

Views: 1013

Answers (3)

Uwe
Uwe

Reputation: 42544

There is an alternative approach which saves the result of each iteration as element of a list and combines the results afterwards. By allocating the list before the loops start, we can avoid costly growing in a loop. Also, this approach is robust in case the order of the loops is changed.

#load libraries    
library(caret)
library(rpart)

#generate data

a = rnorm(1000, 10, 10)

b = rnorm(1000, 10, 5)

c = rnorm(1000, 5, 10)

group <- sample( LETTERS[1:2], 1000, replace=TRUE, prob=c(0.5,0.5) )
group_1 <- 1:1000

#put data into a frame
d = data.frame(a,b,c, group, group_1)

d$group = as.factor(d$group)

#place results in table
#final_table = matrix(1, nrow = 10, ncol=10)

e <- d

vec1 <- sample(200:300,2)
vec2 <- sample(400:500,2)
vec3 <- sample(700:800,2)

result_list <- vector("list", length(vec1)*length(vec2)*length(vec3))
result_count <- 0L

for (i in seq_along(vec1)) { 
  for (j in seq_along(vec2)) {
    for (k in seq_along(vec3)) {
      # d <- e
      d$group_2 = as.integer(ifelse(d$group_1 < vec1[i] , 0, ifelse(d$group_1 >vec1[i]  & d$group_1 < vec2[j] , 1, ifelse(d$group_1 >vec2[j]  & d$group_1 < vec3[k] , 2,3))))
      d$group_2 = as.factor(d$group_2)
      
      fitControl <- trainControl(## 10-fold CV
        method = "repeatedcv",
        number = 2,
        ## repeated ten times
        repeats = 1)
      
      TreeFit <- train(group_2 ~ ., data = d[,-5],
                       method = "rpart",
                       trControl = fitControl)
      
      pred <- predict(
        TreeFit,
        d[,-5])
      
      con <- confusionMatrix(
        d$group_2,
        pred) 
      
      #update results into table
      #final_table[i,j] = con$overall[1]
      acc=c(vec1=vec1[i],vec2=vec2[j],vec3=vec3[k],con$overall[1])
      result_count <- result_count + 1L
      result_list[[result_count]] <- acc
      print(acc)
    }
  }
}

(final_table <- do.call(rbind, result_list))
 

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 389047

You can use expand.grid to create all possible combinations of vec1, vec2 and vec3 and save con$overall[1] on each iteration in the dataframe.

library(caret)
library(rpart)

#generate data

a = rnorm(1000, 10, 10)
b = rnorm(1000, 10, 5)
c = rnorm(1000, 5, 10)
group <- sample( LETTERS[1:2], 1000, replace=TRUE, prob=c(0.5,0.5))
group_1 <- 1:1000

#put data into a frame
d = data.frame(a,b,c, group, group_1)
d$group = as.factor(d$group)

e <- d
vec1 <- sample(200:300, 5)
vec2 <- sample(400:500,5)
vec3 <- sample(700:800,5)
z <- 0
df <- expand.grid(vec1, vec2, vec3)
df$Accuracy <- NA

for (i in seq_along(vec1)) { 
  for (j in seq_along(vec2)) {
    for (k in seq_along(vec3)) {
      # d <- e
      d$group_2 = as.integer(ifelse(d$group_1 < vec1[i] , 0, ifelse(d$group_1 >vec1[i]  & d$group_1 < vec2[j] , 1, ifelse(d$group_1 >vec2[j]  & d$group_1 < vec3[k] , 2,3))))
      
      d$group_2 = as.factor(d$group_2)
      
      fitControl <- trainControl(## 10-fold CV
        method = "repeatedcv",
        number = 2,
        ## repeated ten times
        repeats = 1)
      
      TreeFit <- train(group_2 ~ ., data = d[,-5],
                       method = "rpart",
                       trControl = fitControl)
      
      pred <- predict(
        TreeFit,
        d[,-5])
      
      con <- confusionMatrix(
        d$group_2,
        pred) 
      
      #update results into table
      #final_table[i,j] = con$overall[1]
      z <- z + 1
      df$Accuracy[z] <- con$overall[1]
    }
  }
}

head(df)

#  Var1 Var2 Var3 Accuracy
#1  300  492  767    0.299
#2  202  492  767    0.299
#3  232  492  767    0.299
#4  293  492  767    0.376
#5  231  492  767    0.299
#6  300  435  767    0.331

Upvotes: 1

pascal
pascal

Reputation: 1085

Very nice example you posted here. To initiate your data frame we can add:

#place results in table
final_table = data.frame(vec1=double(),vec2=double(),vec3=double(),Accuracy=double())

We can store the output of acc into it with:

#update results into table
acc=c(vec1[i],vec2[j],vec3[k],con$overall[1])
final_table<-rbind(final_table,acc)

Upvotes: 2

Related Questions