按 R 中的行条件子集

Subsetting by row condition in R

我正在尝试找出一种方法来对纯数字矩阵(即没有 column/row 名称)进行子集化。为了以工作示例的形式进行说明,我想删除不符合逻辑条件的行。

set.seed(42)
m <- matrix(sample.int(100, 10*10, TRUE), 10, 10)

假设我想制作一个子集,所以我保留最大行值为 90 或以上的行,但删除不满足此条件的行。

我能想到的唯一方法是通过 if/else 循环 (max(m[i,]) > 90),但我觉得必须有更优雅的方法来做到这一点。

有什么想法吗?

您可以分几步完成。

首先,使用 apply 在行上找到行的最大值:

maxima = apply(m, 1, max)
# [1] 92 99 99 98 93 96 98 91 98 84

接下来,获取那些大于您的阈值的:

above = maxima >= 90
# [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

现在,使用它来对您的数据进行子集化:

m[above, ]

或者,在一行中:

m[apply(m, 1, max) >= 90, ]

条件可以任意扩展。例如,要测试最大值是否在 两个值之间,您可以这样做:

between = function (x, lower, upper)
    x >= lower & x <= upper

m[between(apply(m, 1, max), 90, 97), ]

您可以使用 m >= 90 简单地创建一个逻辑矩阵。这是可能的,因为 > 是具有 matrix 方法的通用函数(有关具有类似行为的其他函数,请参见 ?S4groupGeneric)。然后,我们可以 运行 rowSums 检查条件是否适用,例如

m[rowSums(m >= 90) > 0, ]

这意味着如果 任何 值等于或高于 90,肯定最大值也更高 - 所以无需首先寻找最大值。


另一种选择是使用非常高效的 matrixStats 包及其 rowMaxs 函数

library(matrixStats)
m[rowMaxs(m) >= 90, ]

根据您的意见,这里有一个可能的矢量化范围解决方案

Maxima <- rowMaxs(m)
m[Maxima >= 90 & Maxima <= 97, ]