仅当组中存在给定行时,数据表才对组应用过滤器
datatable apply filter on groups only if a given row exists in the group
我试图仅在特定值存在时才对 datatable
中的组应用过滤器。如果不存在,则过滤器不适用,并且保留该组的所有行。类似于
我正在寻找 答案的数据 table 版本,如果可能的话,但有一些额外的标准。
首先,我尝试了以下方法:
test <- data.table(grp=c(1,1,1,10,10,10,12,12), c=c("a", "b", "c", "b", "c", "c","a","b"))
test[test[, .I[c=="a" | all(c!="a")], by = grp]$V1]
欢迎提出改进建议。
我试图合并的其他标准是检查 grp 是否属于另一个列表。如果属于列表,则适用过滤器
lst <- c("1", "8")
test[test[, .I[(c=="a" & grp %in% lst) | all(c!="a")], by = grp]$V1]
此处,过滤器仅适用于 grp 值 1 而不适用于 12,因为它在 lst 中不存在。它没有返回所有 grp 值为 12 的行,而是完全删除它们。显然,这是错误的,我想知道如何合并条件。
预期结果:
grp c
1: 1 a
2: 10 b
3: 10 c
4: 10 c
5: 12 a
6: 12 b
对于 grp=1,它存在于 lst 中,因此应用了过滤器。
对于 grp=10,不需要过滤器,因为没有一行带有 c="a"
对于 grp=12,filter 是适用的,但因为它不属于 lst,所以不使用 filter。
谢谢
这是一个使用辅助列的解决方案:
> test <- data.table(grp=c(1,1,1,10,10,10,12,12), c=c("a", "b", "c", "b", "c", "c","a","b"))
> lst <- c(1, 8)
> dtFiltered <- test[, filtera := !all(c != "a") & (grp %in% lst), by = grp][!filtera | c == "a"][, filtera := NULL]
这是使用相同逻辑的一种方法。除了 OP 的逻辑之外,将 OR
(|
) 条件添加到 return 组中未包含在 'lst' 对象
中的所有行
test[test[, all(c != 'a')| (c == 'a' & .BY %in% lst)|
!.BY %in% lst, by = grp]$V1]
-输出
# grp c
#1: 1 a
#2: 10 b
#3: 10 c
#4: 10 c
#5: 12 a
#6: 12 b
或者我们可以使用 if/else
条件
test[test[, .I[if(!.BY %in% lst) TRUE else
(c=="a" & grp %in% lst) | all(c!="a")] , by = grp]$V1]
我试图仅在特定值存在时才对 datatable
中的组应用过滤器。如果不存在,则过滤器不适用,并且保留该组的所有行。类似于
我正在寻找
首先,我尝试了以下方法:
test <- data.table(grp=c(1,1,1,10,10,10,12,12), c=c("a", "b", "c", "b", "c", "c","a","b"))
test[test[, .I[c=="a" | all(c!="a")], by = grp]$V1]
欢迎提出改进建议。
我试图合并的其他标准是检查 grp 是否属于另一个列表。如果属于列表,则适用过滤器
lst <- c("1", "8")
test[test[, .I[(c=="a" & grp %in% lst) | all(c!="a")], by = grp]$V1]
此处,过滤器仅适用于 grp 值 1 而不适用于 12,因为它在 lst 中不存在。它没有返回所有 grp 值为 12 的行,而是完全删除它们。显然,这是错误的,我想知道如何合并条件。
预期结果:
grp c
1: 1 a
2: 10 b
3: 10 c
4: 10 c
5: 12 a
6: 12 b
对于 grp=1,它存在于 lst 中,因此应用了过滤器。 对于 grp=10,不需要过滤器,因为没有一行带有 c="a" 对于 grp=12,filter 是适用的,但因为它不属于 lst,所以不使用 filter。
谢谢
这是一个使用辅助列的解决方案:
> test <- data.table(grp=c(1,1,1,10,10,10,12,12), c=c("a", "b", "c", "b", "c", "c","a","b"))
> lst <- c(1, 8)
> dtFiltered <- test[, filtera := !all(c != "a") & (grp %in% lst), by = grp][!filtera | c == "a"][, filtera := NULL]
这是使用相同逻辑的一种方法。除了 OP 的逻辑之外,将 OR
(|
) 条件添加到 return 组中未包含在 'lst' 对象
test[test[, all(c != 'a')| (c == 'a' & .BY %in% lst)|
!.BY %in% lst, by = grp]$V1]
-输出
# grp c
#1: 1 a
#2: 10 b
#3: 10 c
#4: 10 c
#5: 12 a
#6: 12 b
或者我们可以使用 if/else
条件
test[test[, .I[if(!.BY %in% lst) TRUE else
(c=="a" & grp %in% lst) | all(c!="a")] , by = grp]$V1]