【发布时间】:2020-04-13 15:12:37
【问题描述】:
我试图在一个循环中运行多个条件语句。我的第一个条件是 if, else if 有 3 个条件(如果没有匹配项,技术上是 4 个)。我的第二个确实只需要一个条件,如果不满足该条件,我想保留原始行值。问题是我的输出与行号不匹配,我不确定如何只输出到循环中的特定行。
我想遍历每一列,并且在每一列中我使用sapply 来检查每个值是否落在range1 之外(标记为4),在range1 之内(标记为1) ,is.na(标记为9),否则标记为-999。然后将使用更窄的范围,如果列中的每个值都在 range2 内,则用3 标记,否则不要更新。
我的部分工作代码和一个可重现的示例如下。我的输入和第一个循环是:
df <- structure(list(A = c(-2, 3, 5, 10, NA), A.c = c(NA, NA, NA, NA, NA), B = c(2.2, -55, 3, NA, 99), B.c = c(NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -5L))
> df
A A.c B B.c
1 -2 NA 2.2 NA
2 3 NA -55.0 NA
3 5 NA 3.0 NA
4 10 NA NA NA
5 NA NA 99.0 NA
min1 <- 0
max1 <- 8
test1.func <- function(x) {
val <- if (!is.na(x) & is.numeric(x) & (x < min1 | x > max1){
num = 4
} else if (!is.na(x) & is.numeric(x) & x >= min1 & x <= max1){
num = 1
} else if (is.na(x)){# TODO it would be better to make this just what is already present in the row
} else {
num = -999
}
val
}
Test1 <- function(x) {
i <- NA
for(i in seq(from = 1, to = ncol(x), by = 2)){
x[, i + 1] <- sapply(x[[i]], test1.func)
}
x
}
df_result <- Test1(df)
> df_result
A A.c B B.c
1 -2 4 2.2 1
2 3 1 -55.0 4
3 5 1 3.0 1
4 10 4 NA 9
5 NA 9 99.0 4
下一个循环和条件(任何现有的 4 或 9 值都将保留):
min2 <- 3
max2 <- 5
test2.func <- function(x) {
val <- if (!is.na(x) & is.numeric(x) & (x < min2 | x > max2){
num = 3
}
val
}
Test2 <- function(x) {
i <- NA
for(i in seq(from = 1, to = ncol(x), by = 2)){
x[, i + 1] <- sapply(x[[i]], test2.func)
}
x
}
df_result2 <- Test2(df_result)
# Only 2.2 matches, if working correctly would output
> df_result2
A A.c B B.c
1 -2 4 2.2 3
2 3 1 -55.0 4
3 5 1 3.0 1
4 10 4 NA 9
5 NA 9 99.0 4
当前代码错误,因为只有一个匹配项:
Warning messages:
1: In `[<-.data.frame`(`*tmp*`, , i + 1, value = list(3, NULL, NULL, :
provided 5 variables to replace 1 variables
【问题讨论】:
-
你能用一两句话概括一下逻辑吗?
-
该错误发生在哪里?顺便说一句,在
if语句中使用&(单个)是不好的做法,请改用&&(和||)(参见stackoverflow.com/q/16027840/3358272 和?Logic)。 -
@NelsonGon 逻辑是,(循环1)如果在min1和max1之外,返回4(失败),如果是NA,返回9,如果通过返回1 ,否则返回 -999。在循环 2 中,跳过循环 1 返回 4 或 9 的任何行,如果值超出 min2 和 max2,则返回 3。
-
另外,我强烈建议您在复杂条件下使用一些括号。
!is.na(x) & is.numeric(x) & x < min1 | !is.na(x) & is.numeric(x) & x > max1会比(!is.na(x) & is.numeric(x) & x < min1) | (!is.na(x) & is.numeric(x) & x > max1)更清晰(如果这就是您的意思),然后可以将其简化为!is.na(x) & is.numeric(x) & (x < min1 | x > max1)... 如果您首先检查数字,然后检查缺失,然后检查数字条件,则可能会进一步简化反之亦然。 -
但是,总的来说,当 Nelson 要求提供摘要时,如果您从 之类的内容开始会很有帮助。我想遍历每一列。在每一列中,我使用
sapply检查每个值以查看..."。听到您陈述这些内容将有助于我们确认您的代码尝试符合您的意图。