0

I have example data as follows:

library(data.table)
set.seed(1)
DT <- data.table(panelID = sample(50,50),                                                    # Creates a panel ID
                      Country = c(rep("Albania",30),rep("Belarus",50), rep("Chilipepper",20)),       
                      some_NA = sample(0:5, 6),                                             
                      some_NA_factor = sample(0:5, 6),         
                      Group = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)),
                      Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5),
                      wt = 15*round(runif(100)/10,2),
                      Income = round(rnorm(10,-5,5),2),
                      Happiness = sample(10,10),
                      Sex = round(rnorm(10,0.75,0.3),2),
                      Age = sample(100,100),
                      Educ = round(rnorm(10,0.75,0.3),2))           
DT [, uniqueID := .I]                                                                        # Creates a unique ID                                                                                # https://stackoverflow.com/questions/11036989/replace-all-0-values-to-na
DT$some_NA_factor <- factor(DT$some_NA_factor)
DT$Group <- as.character(DT$Group)

The second DT, DT2, is just a copy of DT with one additional change in the Group column, namely a string value.

DT2 <- copy(DT)
DT2[2,5] <- "something"

What I want to do, to convert columns (in this case colum 5 Group) to numeric if that is possible for most values. The (already working) code to do this is as follows:

# Put object names in the environment in a vector 
dfs <- ls()

conv_to_num_check <- function(z) is.character(z) && (mean(grepl("^ *-?[\\d.]+(?:e-?\\d+)?$", z, perl = TRUE), na.rm=TRUE)>0.9)

for (i in seq_along(dfs)) {
fetch_cols <- which(sapply(get(dfs[i]), conv_to_num_check))
  setDT(get(dfs[i]))[, (fetch_cols) := lapply(.SD, as.numeric), .SDcols = fetch_cols]
}

But because I thought this might go wrong (because of non data.frames in the environment), I put it in a tryCatch. The behaviour of the tryCatch is however not as I expected, because it ends up not changing DT2.

for (i in seq_along(dfs)) {
  tryCatch(
    expr = {
      fetch_cols <- which(sapply(get(dfs[i]), conv_to_num_check))
      print(paste0("The following columns of ", dfs[i], " will be converted (named interger (0) = no columns converted)"))
      print(fetch_cols)
      print("BEFORE")
      print(str(get(dfs[i])))
      setDT(get(dfs[i]))[, (fetch_cols) := lapply(.SD, as.numeric), .SDcols = fetch_cols]
      print("AFTER")
      print(str(get(dfs[i])))
      }, error = function(e){ #Do this if an error is caught...
      }, warning = function(w){ # Do this if an warning is caught...
      }, finally = {# Do this at the end before quitting the tryCatch structure.
      }
  )
}

Could someone explain to me why this is the case?

Is there a better way to make sure that my code does not crash?

Tom
  • 2,173
  • 1
  • 17
  • 44
  • 1
    Can you try by removing the warning or comment out ` #}, warning = function(w){ # Do this if an warning is caught...` when you convert to numeric, it throws a warning. # it is not saying what to do when there is a warning – akrun Apr 20 '22 at 15:30
  • Thank you, it works! I thought I left it optional this way, but apparently I did not understand the example well enough. – Tom Apr 20 '22 at 15:35
  • 1
    If you check the source code of warning, it does `withRestarts({`. If you want to register the warnings, try https://stackoverflow.com/questions/37836392/r-log-warnings-and-continue-execution – akrun Apr 20 '22 at 15:35

0 Answers0