Catching an error based on unique id values in a data.frame

Viewed 63

I want to create a stop() for my data.frame below such that for each unique id, if pos is varying (e.g., consisting of 1s, 2s,etc.), then, if mp values for the rows for which cont==TRUE are not the same, we should throw an error.

Is this possible in R?

In the below toy example, id == "B" should throw an error because, pos is varying (1,2,3), and mp values (i.e., 1,3) for the rows for which cont==TRUE are not the same.

dat <- data.frame(id = rep(c("A","B"),2:3), mp = c(1,5, 2,1,3), cont = c(F,T, F,T,T), pos = c(1,1, 1:3))
#  id mp  cont pos
#1  A  1 FALSE   1
#2  A  5  TRUE   1
#3  B  2 FALSE   1
#4  B  1  TRUE   2
#5  B  3  TRUE   3

# Desired stop() message:
"Error: 'B' has a wrong value."
1 Answers

In base R, one option is to split the subset of data i.e where 'cont' is TRUE by 'id' into a list. Then loop over the list along with the names of the list in Map, check if the unique rows have more than 1 row, then call the stop

lst1 <- split(dat[dat$cont,c("mp", "pos")], dat$id[dat$cont])
Map(function(x, y) if(nrow(unique(x)) > 1)  
     stop(sprintf("'%s' has a wrong value.", y), call. = FALSE), 
        lst1, names(lst1))
#Error: 'B' has a wrong value.

With the updated example

lst1 <- split(dat[dat$control, c("mpre", "post")], dat$study.name[dat$control])
Map(function(x, y) if(all(lengths(lapply(x, unique))  > 1))  
      stop(dQuote(sprintf("'%s' has a wrong value.", y), FALSE), call. = FALSE), 
         lst1, names(lst1))
#Error: "'Brown' has a wrong value."
Related