我有一个与此类似的 data.table (df):
df <- read.table(header=TRUE, text='
ID AltID Crit1 Crit2 Crit3
1 1 1 5 10
1 2 3 7 15
1 3 2 6 11')
对于每个
Crit
-column 我有一个这样的上限和下限:minCutoff = c(0, 5, 10)
maxCutoff = c(4, 7, 12)
从 data.table (df) 计算得出。
我想要一个函数,它排除一个值超出范围的任何行。此外,我希望此函数能够使用可变数量的
Crit
列(例如 3 个 Crit 列、4 个 Crit 列等),因为我的输入数据可能会发生变化。因此,对于此示例,尽管
Crit3 (15) > maxCutoff (12)
和 Crit1
在可接受的范围内,但第 1 行和第 3 行将被保留,但第 2 行将被丢弃,因为其 Crit2
。因此,输出将是:ID AltID Crit1 Crit2 Crit3
1 1 1 5 10
1 3 2 6 11
我已经尝试使用
for
循环来计算我拥有的列数,然后使用嵌套的 for 循环来使用类似...for (c in 1:(ncol(df)-2)+2)
{
for (r in 1:nrow(df))
{
between(df[r,c], minCutoff[c], maxCutoff[c])
}
}
*
ncol(df)-2)+2
是由于围绕 ID 列工作但是,现在我有 TON 的 T/F 值,我无法聚合这些值来确定是否应该保留或丢弃一行。
我确信有一种神奇的 R 方法可以使这个过程更简单,但我不够熟练,无法看到它。
如果有人有任何提示、技巧或其他线索来为我指明正确的方向,我将不胜感激。
最佳答案
您的数据:
df <- read.table(header=TRUE, text='
ID AltID Crit1 Crit2 Crit3
1 1 1 5 10
1 2 3 7 15
1 3 2 6 11')
minCutoff = c(0, 5, 10)
maxCutoff = c(4, 7, 12)
特尔;博士:
df[rowSums(mapply(between, df[ grep("Crit", colnames(df)) ], minCutoff, maxCutoff)) >= 3,]
# ID AltID Crit1 Crit2 Crit3
# 1 1 1 1 5 10
# 3 1 3 2 6 11
使用一个函数可以轻松处理可变数量的
Crit
列,依次应用于每个列,然后聚合结果。如果您已经在使用 dplyr
包,那么您已经有了 dplyr::between
,但如果没有,那么这里是一个可接受的替代品:between <- function(x, low, hi) low <= x & x <= hi
我将带您完成工作:
isbetween <- mapply(between, df[ grep("Crit", colnames(df)) ], minCutoff, maxCutoff)
isbetween
# Crit1 Crit2 Crit3
# [1,] TRUE TRUE TRUE
# [2,] TRUE TRUE FALSE
# [3,] TRUE TRUE TRUE
df[grepl("Crit", colnames(df)) ]
是一种(多种)方式,用于查看您感兴趣的列; mapply
应用一个函数(在本例中为 between
),其中包含每个其他列表/向量的第一个值。它实际上等同于:between(df[3], minCutoff[1], maxCutoff[1])
between(df[4], minCutoff[2], maxCutoff[2])
...
现在我们在各自的截止值内有一个单独值的逻辑矩阵,我们查看每一行以检查它们是否满足您的过滤器要求 3 或更多。不幸的是,您列出的预期输出与您的规则不兼容,因此我将提供一些替代方案:
FALSE
有 3 列或更多列,则应删除该行rowSums(!isbetween) >= 3
# [1] FALSE FALSE FALSE
rowSums(isbetween) >= 3
# [1] TRUE FALSE TRUE
无论您选择哪个,都使用此逻辑向量并对行进行子集化,例如
df[rowSums(isbetween) >= 3,]
# ID AltID Crit1 Crit2 Crit3
# 1 1 1 1 5 10
# 3 1 3 2 6 11
(Rui's answer 和 this 之间的最大区别在于,该答案在
apply
上使用 data.frame
进行行操作,将相关列隐式转换为矩阵。我的答案按列进行(使用框架进行自然操作),因此未进行任何转换. 除了这种转换,如果框架不是很大,那么 row-wise 和 column-wise 的性能应该大致相同。如果它在很大程度上是不对称的(例如,行比列多得多),那么它可能是一个以列方式工作的速度稍快。R 中的矢量化工作几乎总是比迭代快得多。)关于r - 过滤位于 2 个数字向量之间的数据表行向量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51770443/