我想知道是否可以用等效的 for()
系列替换我的 *apply()
循环?
我已经尝试过 lapply()
,但我无法让它工作。这在 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)
}
}
}
}
答案 0 :(得分:1)
类似的选项是
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.
如果我们也想返回 message
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.