后续:为 data.frame 中的每个 id 值创建错误消息
Follow-up: Creating error message for each id value in a data.frame
我正在跟进 的回答。我想为下面的 data.frame 创建一个 stop()
。具体来说,对于每个唯一的 id
值,如果 pos
是变化的(即不恒定),则 对于 out
的任何唯一值(例如 1)每个 id
,如果 cont==TRUE
行的任何 mp
值不相同,我们应该抛出错误。
这在 BASE R 中可行吗?
在下面的玩具示例中,id == "B"
应该抛出错误,因为 pos
是变化的 (1,2,3),并且对于 out == 2
下的唯一值 id == "B"
、mp
值(第 7 行和第 8 行)是 cont==TRUE
不相同的行(即 5
和 6
)。
我当前的解决方案没有捕捉到这个错误(如下)。
(dat <- data.frame(id=rep(c("A", "B"), c(2, 6)), mp=c(1, 5, 2, 3, 1, 1, 5, 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)))
# 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 3 FALSE 2 1
#5 B 1 TRUE 1 1
#6 B 1 TRUE 2 1
#7 B 5 TRUE 1 2
#8 B 6 TRUE 2 2
# Desired stop() message:
"Error: 'B' has a wrong value."
## My current solution (doesn't `stop()`):
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]))
}
})
更新:
接下来,如果我们有一个名为 sp
的附加列,并且希望 sp
的条件与 mp
完全相同,那么 @kews
解决方案变化?
(NEW_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, .5),
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 sp cont pos out
#1 A 1 0.2 FALSE 1 1
#2 A 5 0.3 TRUE 1 1
#3 B 2 0.2 FALSE 1 1
#4 B 1 0.2 FALSE 2 1
#5 B 1 0.2 TRUE 1 1
#6 B 1 0.2 TRUE 2 1
#7 B 6 0.6 TRUE 1 2
#8 B 6 0.5 TRUE 2 2
这符合问题中的逻辑。
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"]
mps_constant <- (length(unique(mps)) %in% c(1,0))
if (!mps_constant) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]))
}
}
}
编辑:
添加了控制流程以检查 sp
列上的相同条件,同样的事情具有完全相同的 *_constant
逻辑。
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))
if (!mps_constant | !sps_constant) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]))
}
}
}
我正在跟进 stop()
。具体来说,对于每个唯一的 id
值,如果 pos
是变化的(即不恒定),则 对于 out
的任何唯一值(例如 1)每个 id
,如果 cont==TRUE
行的任何 mp
值不相同,我们应该抛出错误。
这在 BASE R 中可行吗?
在下面的玩具示例中,id == "B"
应该抛出错误,因为 pos
是变化的 (1,2,3),并且对于 out == 2
下的唯一值 id == "B"
、mp
值(第 7 行和第 8 行)是 cont==TRUE
不相同的行(即 5
和 6
)。
我当前的解决方案没有捕捉到这个错误(如下)。
(dat <- data.frame(id=rep(c("A", "B"), c(2, 6)), mp=c(1, 5, 2, 3, 1, 1, 5, 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)))
# 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 3 FALSE 2 1
#5 B 1 TRUE 1 1
#6 B 1 TRUE 2 1
#7 B 5 TRUE 1 2
#8 B 6 TRUE 2 2
# Desired stop() message:
"Error: 'B' has a wrong value."
## My current solution (doesn't `stop()`):
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]))
}
})
更新:
接下来,如果我们有一个名为 sp
的附加列,并且希望 sp
的条件与 mp
完全相同,那么 @kews
解决方案变化?
(NEW_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, .5),
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 sp cont pos out
#1 A 1 0.2 FALSE 1 1
#2 A 5 0.3 TRUE 1 1
#3 B 2 0.2 FALSE 1 1
#4 B 1 0.2 FALSE 2 1
#5 B 1 0.2 TRUE 1 1
#6 B 1 0.2 TRUE 2 1
#7 B 6 0.6 TRUE 1 2
#8 B 6 0.5 TRUE 2 2
这符合问题中的逻辑。
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"]
mps_constant <- (length(unique(mps)) %in% c(1,0))
if (!mps_constant) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]))
}
}
}
编辑:
添加了控制流程以检查 sp
列上的相同条件,同样的事情具有完全相同的 *_constant
逻辑。
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))
if (!mps_constant | !sps_constant) {
stop(sprintf("'%s' has a wrong value.", x[,"id"][1]))
}
}
}