【问题标题】:Check rows from all columns that matches specific value检查与特定值匹配的所有列中的行
【发布时间】:2018-07-27 19:00:15
【问题描述】:

如果我有data.table:

d <- data.table("ID" = c(1, 2, 2, 4, 6, 6), 
                "TYPE" = c(1, 1, 2, 2, 3, 3), 
                "CLASS" = c(1, 2, 3, 4, 5, 6))

我知道我可以像这样删除大于特定值的值:

r <- d[!(d$TYPE > 2), ]

但是,如果我想将其应用于整个表中的 所有 列,而不仅仅是 TYPE(基本上删除整个表中值 > 2 的任何行),我将如何概括上述语句(如果可能,避免使用for 循环)。

我知道我可以通过 d &gt; 2 生成一个布尔索引表,但如果我将它放入上面的代码行中,它会给我一个错误:

d[!d>2, ]

导致invalid matrix type

注意

有人提出这个问题类似于Return an entire row if the value in any specific set of columns meets a certain criteria。 但是,他们使用的是data.frame,而我使用的是data.table,符号不同。因此不是重复的问题。

【问题讨论】:

标签: r data.table


【解决方案1】:

applyany 一起使用

d[!apply(d>2,1,any)]
   ID TYPE CLASS
1:  1    1     1
2:  2    1     2

rowSums

d[rowSums(d>2)==0,]
   ID TYPE CLASS
1:  1    1     1
2:  2    1     2

【讨论】:

  • 如果我们想忽略ID 列怎么办? @文
  • @KAS d[rowSums((d&gt;2)[,!(colnames(d) == "ID")])==0,]d[!apply((d&gt;2)[,!(colnames(d) == "ID")],1,any)]
  • d[rowSums(d[, -'ID'] &gt; 2) == 0]
【解决方案2】:

我想知道对于不同数量的行和列,最快的方法是什么。

所以,这是一个基准。

它排除了 ID 列的检查,这不完全符合 OP 的问题,但这是一个明智的决定,恕我直言。

library(data.table)
library(bench)
bm <- press(
  n_row = c(1E1, 1E3, 1E5),
  n_col = c(2, 10, 50),
  {  
    set.seed(1L)
    d <- data.table(
      ID = seq_len(n_row),
      matrix(sample(10, n_row*n_col, TRUE), ncol = n_col)
    )
    mark(
      m1 = d[d[, !apply(.SD > 2, 1, any), .SDcols = -"ID"]],
      m2 = d[!d[, apply(.SD > 2, 1, any), .SDcols = -"ID"]],
      m3 = d[!d[, which(apply(.SD > 2, 1, any)), .SDcols = -"ID"]],
      m4 = d[d[, rowSums(.SD > 2) == 0, .SDcols = -"ID"]],
      m5 = d[!d[, Reduce(any, lapply(.SD, `>`, y = 2)), by = 1:nrow(d), .SDcols = -"ID"]$V1]
    )
  })

ggplot2::autoplot(bm)

显然,rowSums() 方法几乎总是最快的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 2023-02-22
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    相关资源
    最近更新 更多