我正在跟进这个问题。我想为下面的数据帧创建一个stop()
。具体地说,对于每个唯一的id
值,如果pos
是变化的(例如,由1、2s等组成(,那么对于每个id
下的out
的每个唯一值(例如,1(,如果对于cont==TRUE
不相同的行的mp
值,我们应该抛出错误。
这在R中可能吗?
在下面的玩具示例中,id == "B"
应该抛出错误,因为pos
是变化的(1,2,3(,并且对于id == "B"
下的out
的每个唯一值(例如,1(,cont==TRUE
不相同的行的mp
值。
dat <- data.frame(id=rep(c("A", "B"), c(2, 6)), mp=c(1, 5, 2, 1, 3, 4, 6, 0),
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))
# id mp cont pos out
#1 A 1 FALSE 1 1
#2 A 5 TRUE 1 1
#3 B 2 FALSE 1 1
#4 B 1 FALSE 2 1
#5 B 3 TRUE 1 1
#6 B 4 TRUE 2 1
#7 B 6 TRUE 1 2
#8 B 0 TRUE 2 2
# Desired stop() message:
"Error: 'B' has a wrong value."
我们可以使用
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.
您可以试试这个。
sapply(split(dat, dat$id), function(x) {
if (var(x[,'pos']) > 0) {
r <- all(sapply(unique(x[,'out']), function(i)
var(x[x[,'out'] == i & x[,'cont'], 'mp']) > 0))
} else {
r <- FALSE
}
if (r) {
stop(sprintf("Error: '%s' has a wrong value.", x[,'id'][1]))
}
})
# Error in FUN(X[[i]], ...) : Error: 'B' has a wrong value.
这里有一个非常详细的答案,希望它有用。
library(dplyr)
dat %>%
filter(cont) %>%
group_by(id, out) %>%
mutate(varying_mp = n_distinct(mp) > 1) %>%
group_by(id) %>%
mutate(varying_pos = n_distinct(pos) > 1,
all_varying_mp = min(varying_mp)) %>%
filter(varying_pos & all_varying_mp) %>%
slice(1) %>%
pull(id) -> wrong_val_ids
if(!is.null(length(wrong_val_ids))) stop(paste("Error: ", paste(wrong_val_ids, collapse = ","), "has a wrong value"))