【问题标题】:datatable apply filter on groups only if a given row exists in the group仅当组中存在给定行时,数据表才对组应用过滤器
【发布时间】:2021-07-29 22:39:41
【问题描述】:

我正在尝试仅在存在特定值的情况下将过滤器应用于datatable 中的组。如果不存在,则过滤器不适用并保留组的所有行。类似于this

如果可能的话,我正在寻找this 答案的数据表版本,但带有一些附加条件。

首先,我尝试了以下方法:

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,过滤器是适用的,但是因为它不属于lst,所以过滤器没有被使用。

谢谢

【问题讨论】:

  • 根据您的条件,为什么要返回 12 的组。您正在做 grp %in% lst 而这不是 12 的情况
  • 你的lst &lt;- c("1", "8") 不包括12
  • 我又添加了一个条件来返回该组不包括在内的情况
  • 是的,我只想将过滤器应用于 grp="1" 而不是 grp="12",尽管它们都有 c="a"。我知道我错了。在我看来,它就像嵌套的 if 条件,但我不知道如何在这里应用它。
  • 请检查下面的代码。我发了两个案例。可能是其中之一帮助

标签: r if-statement filter datatable nested


【解决方案1】:

这是使用相同逻辑的一种方法。除了 OP 的逻辑之外,添加一个OR (|) 条件以返回未包含在 'lst' 对象中的所有 group 行

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]

【讨论】:

  • 当 'grp' 列是 factorcharacter 时,上述行为是否会有所不同?似乎它正在有所作为。谢谢!
  • @K_D 最好转成charactercass
【解决方案2】:

这是一个使用辅助列的解决方案:

> 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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多