3

我有一个 30,000 行和 3 列的数字矩阵。我想根据矩阵每一行中的 3 个值生成一个简单的 PASS/FAIL 向量(或因子)。我想应用以下逻辑:

如果行中的所有 3 个值 > 3,则输入 PASS,否则输入 FAIL。

我知道如何使用 for 循环来做到这一点,但我怎样才能更快地做到这一点?我有几十个这样的矩阵......谢谢!

as.matrix(rbind(c(129,129,120),c(135,97,96),c(0,0,0),c(39,4,2)))

所需的输出:通过、通过、失败、失败

4

5 回答 5

5

使用alland apply(虽然apply使用它自己的循环)。

m <- as.matrix(rbind(c(129,129,120),c(135,97,96),c(0,0,0),c(39,4,2)))

apply(m, 1, function(x) all(x > 3))
# [1]  TRUE  TRUE FALSE FALSE

如果您真的想要“PASS”和“FAIL”,则可以factor使用该apply步骤的结果。

factor(apply(m, 1, function(x) all(x > 3)), 
       levels = c(FALSE, TRUE), 
       labels = c("FAIL", "PASS"))
# [1] PASS PASS FAIL FAIL
# Levels: FAIL PASS

稍微扩展 Codoremifa 的答案,类似的方法适用于data.table,特别是因为您指定了您想要一个向量或因子作为输出。

library(data.table)
DT <- data.table(m)
DT[, all(.SD > 3), by = 1:nrow(DT)][, factor(V1, labels = c("FAIL", "PASS"))]
# [1] PASS PASS FAIL FAIL
# Levels: FAIL PASS
于 2013-10-22T18:02:40.793 回答
4

与此处的其他答案不同,这使用rowSums但不是在 R 中循环,并且可以超过多个子集和逻辑。这应该是最快的路线了。

mat <- as.matrix(rbind(c(129,129,120),c(135,97,96),c(0,0,0),c(39,4,2)))

vec <- ifelse(rowSums(mat > 3) == 3, TRUE, FALSE)

我们还可以绕过ifelse并使其更快。

vec <- rowSums(mat > 3) == 3

如果你测试这些时间,那可能是赢家。在我的系统上,使用 30,000 个行矩阵,我的第一个答案的输出速度大约是 gung 答案的两倍,第二个答案的输出速度是 10 倍,并且可以在大约 2 秒内在 1000 个 30,000 行矩阵上执行。Codoremifa 答案是data.table这里最快的答案,需要 20 秒(类似于 gung 答案)。

注意:我有点忽略了您对“PASS”、“FAIL”向量的请求,因为您似乎表示速度至关重要,而且这是一个微不足道的语义区别。此外,如果需要,逻辑向量已经准备好对矩阵进行子集化。

于 2013-10-22T18:30:25.040 回答
2
library(data.table)
dt <- as.matrix(rbind(c(129,129,120),c(135,97,96),c(0,0,0),c(39,4,2)))

dt <- data.table(dt)
dt[, Indicator :="FAIL"]
dt[V1 > 3 & V2 >3 & V3 >3, Indicator :="PASS" ]
于 2013-10-22T18:01:11.170 回答
2

另外,mapply

mat <- as.matrix(rbind(c(129,129,120),c(135,97,96),c(0,0,0),c(39,4,2)))

fun <- function(x, y, z) { ifelse(x > 3 & y > 3 & z > 3, "PASS", "FAIL") } 
mapply(fun, mat[,1], mat[,2], mat[,3])
#[1] "PASS" "PASS" "FAIL" "FAIL"
于 2013-10-22T18:08:55.567 回答
1

对于这样的问题,我的第一个倾向是结合?all?apply和 & ?ifelse,也许就像@Ananda 提供的解决方案一样。正如他所提到的,apply() 正在使用循环。如果您想要一个完全矢量化的解决方案,您可以尝试:

newVector <- ifelse((xMatrix[,1]>3 & xMatrix[,2]>3 & xMatrix[,3]>3), 
                    "PASS", "FAIL")

矢量化是 R 的一个方便的特性,它比循环快得多。您可以在此处阅读有关矢量化的信息。

于 2013-10-22T18:05:41.013 回答