R: filtering in loop

Viewed 101

I am to perform lm() on different dataset via loop, which should first make dataset using filter() and then to perform lm() on filtered dataset and save the results. However, I always get this error and I have no idea what I am doing wrong.

"Error in contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]]) :
contrasts can be applied only to factors with 2 or more levels"

My code:

a<-c("var1", "var2", "var3") #character vector


for (b in a){
  dataset <- dataset%>%filter(variable_name == b)
  lm<- lm(y ~ x1 + x2, data=dataset)
assign(paste(b, "lm", sep='_'), lm)
}

Can anyone help me please? I know it is really elementary. Based on searching results, I've also tried it with

dataset <- dataset%>%filter(variable_name == **paste0("'",b,"'")**)

but always get the same error...Thanks!

1 Answers

Updating the original object in the global environment with the subset of rows will throw error for the subsequent iterations as == returns 0 rows for 'var2' and 'var3' (when the dataset have only 'var1' value in 'variable_name'). Instead, create a temporary object (which could be removed as well) within the loop

for (b in a){
  tmp <- subset(dataset, variable_name == b)
   model <- lm(y ~ x1 + x2, data = tmp)
   assign(paste(b, "lm", sep='_'), model)
   rm(tmp)
 }

It may be also better to create a single list object instead of multiple objects in the global env. split would be faster than == which splits the data into subset of data in a list based on the values in 'variable_name'

model_lst <- lapply(split(dataset, dataset$variable_name), function(tmp)
          lm(y ~ x1 + x2, data = tmp))

Or if we prefer to use the 'a' vector (assuming there are more unique values in 'variable_name' and want only the models based on 'a' vector)

model_lst <- lapply(a, function(b) {
            lm(y ~ x1 + x2, data = subset(dataset, variable_name == b)
  })
Related