Home > OS >  Breaking while loop containing lists
Breaking while loop containing lists

Time:06-12

I have a function that iterates polynomial expression on a predictor up until the linear model output shows that predictor without significance. This is all done in a while(TRUE) loop because I want to iterate all the degrees of a polynomial (unlikely I would actually need anything greater than 5), however I cannot get the loop to break properly. It should break when the length of the lists are 0 via compact.

For example:

regression_polynomial <- function(data, response_chosen, predictor_chosen){
  pmod <- c()
  pmod_I <- c() 
  i=0
  while(TRUE){
    i = i 1
    form <- reformulate(glue('poly({predictor_chosen},{i}, raw=TRUE)'), response=response_chosen)
     pmod[[i]] <- lm(form, data) %>% summary() %>%
      .$coefficients %>% data.frame(.) %>% rownames_to_column() %>% .[!(.$rowname) %in% "(Intercept)",] %>% 
     `colnames<-`(c('predictor', 'Estimate', 'Std.Error', 't-value', 'Pr(>|t|)')) %>% 
       remove_rownames() %>% split(., sort(as.numeric(rownames(.)))) %>% 
       lapply(., function(x){if(x$`Pr(>|t|)` < 0.05)x } ) %>% 
       compact() 
     length_pmod <- sapply(pmod, length)
     if(length(length_pmod) == 0){
       break
     }


  }
  return(pmod)
}
library(faraway)
regression_polynomial(savings, 'sr', 'pop15')
>Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) : 
NA/NaN/Inf in 'x'

CodePudding user response:

If compact() removes all elements, it will not return NULL but an empty object and that still ends up in pmod. Output vector length of sapply(pmod, length) is also the same as pmod length (i.e. never 0) and thus length(length_pmod) == 0 never evaluates to TRUE

Sample to illustrate:

library(purrr)
pmod <- c()
str(pmod)
#>  NULL
pmod[[1]] <- list(a = NULL) %>% compact()
str(pmod)
#> List of 1
#>  $ : Named list()
length_pmod <- sapply(pmod, length)
str(length_pmod)
#>  int 0
# your break check condition if no results were returned on 1st cycle:
length(length_pmod)
#> [1] 1

But you could just drop the length_pmod <- sapply(pmod, length) and check the length of the last item in pmod vector for your break condition:

ibrary(purrr)
library(dplyr)
pmod <- c()

pmod[[1]] <- list(a = NULL) %>% compact()
# compact() removed all items, time to break
length(last(pmod))
#> [1] 0

pmod[[1]] <- list(a = "not NULL") %>% compact()
# compact() kept something
length(last(pmod))
#> [1] 1
  •  Tags:  
  • r
  • Related