1

Consider the data frame dat:

dat <- data.frame(Loc = c("NY","MA"),
                  ID = c(1:2),
                  Sex = c("M","F")
                  )

Pretending there were a lot more data to go with this, and multiple observations for each ID, I want to fit a model and save it in an object called NYM1mod, which to me would stand for "model for New York Male number 1" I can use: paste(dat[1,1], dat[1,3], dat[1,2],"mod", sep="") to output what I want: [1] "NYM1mod" But how can I do something like this and make the output the name of a new object? For example, why can you not assign the number 3 to the output "NYM1mod" like this?: paste(dat[1,1], dat[1,3], dat[1,2],"mod", sep="") <- 3

Ryan
  • 1,048
  • 7
  • 14
  • 1
    What you may be trying to do is what `assign(paste0(dat[1,1], dat[1,3], dat[1,2], "mod"), 3)` does. – r2evans May 15 '20 at 22:26
  • 1
    But if you're trying to deal with identically-structured frames programmatically, I strongly discourage the notion of `assign` and suggest you can deal with a `list` of `data.frame`s instead. If that seems relevant, please see https://stackoverflow.com/a/24376207/3358272 – r2evans May 15 '20 at 22:27
  • In other words, the programmatic way in R is create a **single** list of *many* objects, one of which is named `NYM1mod` and can be referenced as `mylist$NYM1mod`. – Parfait May 16 '20 at 00:00
  • @Parfait @r2evans This is a good suggestion. My reason for asking this is because I am writing a function that I want to feed an `id` and it will create a model named according to what I have described above. If I create an empty list, and tell the function to add the model to this list, what syntax do I use to name the list element as I have described? – Ryan May 16 '20 at 17:10
  • Build your nameless empty list of models. Then rename with `setNames` + `paste0`: `mylist <- setNames(mylist, paste0(dat$Loc, dat$Sex, dat$ID, "mod"))` – Parfait May 17 '20 at 18:33

1 Answers1

0

As commented, consider using a list instead of many separate objects. Specifically, generalize your modeling process in a defined function. Iterate it with lapply to return a list of objects. Then rename with setNames to return a single, named list of objects, indexable for all. some, or one item without flooding global environment with many, separate objects:

proc_model <- function(...) {
    # MODELING PROCESS 
    ...
    return(model)
}

model_list <- setNames(lapply(sequence_pass_as_params, proc_model),
                       paste0(dat$Loc, dat$Sex, dat$ID, "mod"))

# ALL MODELS
model_list 

# SELECT MODELS
model_list$NYM1mod    
model_list$MAF2mod

In fact, if I understand your needs consider by (another sibling to apply family as object-oriented wrapper to tapply) to pass subset data frames of Loc, ID, and Sex into your modeling function. Wrap process with tryCatch for subsets that do not exist and/or yields modeling errors.

# RECEIVE DATA FRAME AS PARAMETER
proc_model <- function(df) {
    tryCatch({
        # MODELING PROCESS 
        model <- lm(..., data = df)
        }, error = function(e) return(NULL)
    )
}

# BUILD MODEL LIST BY SUBSETS
model_list <- by(dat, dat[,c("Loc", "Sex", "ID"), proc_model)

# RENAME ELEMENTS IN LIST WITH UNIQUE NAMES
model_list <- setNames(model_list, unique(paste0(dat$Loc, dat$Sex, dat$ID, "mod")))

# REMOVE EMPTY MODELS  (I.E., ITEMS THAT RETURN NULL)
model_list <- Filter(model_list, LENGTH)

# ALL MODELS
model_list 

# SELECT MODELS
model_list$NYM1mod    
model_list$MAF2mod
Parfait
  • 104,375
  • 17
  • 94
  • 125