Reputation: 7517
I was wondering if it might be possible to replace my for()
loop with an equivalent *apply()
family?
I have tried lapply()
but I can't get it to work. Is this possible in BASE R?
(dat <- data.frame(id=rep(c("A", "B"), c(2, 6)), mp=c(1, 5, 2, 1, 1, 1, 5, 6), sp=c(.2, .3, .2, .2, .2, .2, .6, .6),
cont=c(F, T, F, F, T, T, T, T), pos=c(1, 1, rep(1:2, 3)),
out=c(1, 1, 1, 1, 1, 1, 2, 2)))
##### for loop:
for (x in split(dat, dat$id)) {
pos_constant <- (length(unique(x$pos)) == 1)
if (pos_constant) {
next
}
group_out <- split(x,x$out)
for (x_sub in group_out) {
mps <- x_sub[x_sub$cont==TRUE,"mp"]
sps <- x_sub[x_sub$cont==TRUE,"sp"]
mps_constant <- length(unique(mps)) %in% c(1,0)
sps_constant <- length(unique(sps)) %in% c(1,0)
r <- !mps_constant || !sps_constant
if (r) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]), call. = FALSE)
}
}
}
##### `lapply()` solution without success:
lapply(split(dat, dat$id), function(x){
pos_constant <- (length(unique(x$pos)) == 1)
if (pos_constant) {
lapply(split(x, x$out), function(x_sub){
mps <- x_sub[x_sub$cont==TRUE,"mp"]
sps <- x_sub[x_sub$cont==TRUE,"sp"]
mps_constant <- length(unique(mps)) %in% c(1,0)
sps_constant <- length(unique(sps)) %in% c(1,0)
r <- !mps_constant || !sps_constant
if (r) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]), call. = FALSE)
}
}
}
}
Upvotes: 1
Views: 102
Reputation: 887138
A similar option is
lapply(split(dat, dat$id), function(x){
pos_constant <- (length(unique(x$pos)) == 1)
if (!pos_constant) {
lapply(split(x, x$out), function(x_sub){
mps <- x_sub[x_sub$cont==TRUE,"mp"]
sps <- x_sub[x_sub$cont==TRUE,"sp"]
mps_constant <- length(unique(mps)) %in% c(1,0)
sps_constant <- length(unique(sps)) %in% c(1,0)
r <- !mps_constant || !sps_constant
if (r) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]), call. = FALSE)
}
})
}
})
#Error: 'B' has a wrong value.
If we want to return message
as well
lapply(split(dat, dat$id), function(x){
pos_constant <- (length(unique(x$pos)) == 1)
if (!pos_constant) {
lapply(split(x, x$out), function(x_sub){
mps <- x_sub[x_sub$cont==TRUE,"mp"]
sps <- x_sub[x_sub$cont==TRUE,"sp"]
mps_constant <- length(unique(mps)) %in% c(1,0)
sps_constant <- length(unique(sps)) %in% c(1,0)
r <- !mps_constant || !sps_constant
if (r) {
stop(sprintf("'%s' has a wrong value.",
x[,"id"][1]), call. = FALSE)
}
})
} else {
message(sprintf("'%s' is ok.", x[,"id"][1]))
}
})
#'A' is ok.
#Error: 'B' has a wrong value.
Upvotes: 1