Search code examples
rloopsif-statementtry-catchskip

How to skip an error in loop while preserving the missing element as a blank column?


I have the following chunk of data:

> dput(data)
structure(c(0.640372781, 0.54596394, 0.364612178, 0.554321638, 
0.623891566, 0.299900389, 0.629781465, 0.502673674, 0.414942748, 
0.485381455, 0.629032253, 0.201974626, 0.549820206, 0.49277897, 
0.299640651, 0.443151949, 0.506297992, 0.259198111, 0.635090505, 
0.597640686, 0.430193856, 0.631067648, 0.662995875, 0.391062922, 
0.632248042, 0.627503454, 0.432827825, 0.418849204, 0.612201188, 
0.227470395, 0.556520484, 0.6095603, 0.414923451, 0.57634896, 
0.543780581, 0.320027087, 0.655818488, 0.648937123, 0.497094053, 
0.429772696, 0.632386262, 0.270060224, 0.564427852, 0.456642259, 
0.492407708, 0.436349654, 0.616355794, 0.248897538, 0.642866477, 
0.555022037, 0.358901689, 0.53184597, 0.606299729, 0.342449093, 
0.667681177, 0.506448197, 0.370292817, 0.555462276, 0.642302168, 
0.42487856, 0.649249462, 0.544035494, 0.394793334, 0.383522657, 
0.557789563, 0.220189788, 0.636151283, 0.547825201, 0.391789202, 
0.653913292, 0.649412792, 0.452257495, 0.648866884, 0.535907987, 
0.392093314, 0.724788138, 0.674157973, 0.494385979, 0.673032345, 
0.450686601, 0.369089571, 0.397124065, 0.502592807, 0.197922003
), class = c("xts", "zoo"), .indexCLASS = "Date", tclass = "Date", .indexTZ = "UTC", tzone = "UTC", index = structure(c(1025049600, 
1025136000, 1025222400, 1025481600, 1025568000, 1025654400), tzone = "UTC", tclass = "Date"), .Dim = c(6L, 
14L), .Dimnames = list(NULL, c("AN8068571086", "BMG3223R1088", 
"BMG4388N1065", "BMG6359F1032", "BMG7496G1033", "BMG812761002", 
"CA88157K1012", "CH0044328745", "CH0048265513", "GB00B4VLR192", 
"GB00B5BT0K07", "GB00B6SLMV12", "GB00BFG3KF26", "GB00BVVBC028"
)))

And this code:

    ######## INPUTS ######

a <- 0.5
b <- 0.6

results <- list() # list containing loop results

#######################


for (i in 1:nrow(data)) {


  input <- as.matrix(data[i,])

  #extract column names with a value between a and b  

  stocks <- matrix(colnames(data[,which(input > a & input < b)]))

  # make a vector with new name for the output
  date   <- head(rownames(input), n=1)

  #rename column  
  colnames(stocks) <- date

  #export to list under "date" name
  results[[date]] <- stocks

}

If you run it exactly as it is you will get this error:

Error in matrix(colnames(data[, which(input > a & input < b)])) : 
  'data' must be of a vector type, was 'NULL'
In addition: Warning messages:
1: In min(j, na.rm = TRUE) :
  no non-missing arguments to min; returning Inf
2: In max(j, na.rm = TRUE) :
  no non-missing arguments to max; returning -Inf

This comes from the third row in data which contains no values between 0.5 and 0.6

matrix(colnames(data[,which(input > a & input < b)]))

After running the above code i run this, which merges all my data together and prepares it for other calculations:

# merge all results in a list 
max_length <- max(sapply(results ,length))

final_results <- sapply(results, function(x){
  c(x, rep(NA, max_length - length(x)))
})

i need a way to skip that error while still preserving the date name as a blank column in final_results. I am thinking maybe an if function such that if there are no values that lie between a and b an empty matrix of (1x1) is created with the colname = date which should be stored in results list.

another option would be using tryCatch but that will omit the date entirely and between the thousands that i have here it will be impossible to find missing columns.


Solution

  • If you use the tryCatch function that processes your error by returning a matrix with NA value you would get a column with the appropriate date as a name that only contains NA in your final_results. However this would process all errors in the same way so may not be the best solution if your data could throw up different errors.

        stocks <- tryCatch(matrix(colnames(data[,which(input > a & input < b)])), 
                           error = function(e) matrix(NA))