Select 行至少有一个(任意)负值

Select rows with at least one (any) negative value

我想创建一个新的 data.table,其中包含至少有一个负值的所有行。

这是一个简单的可重现数据表:

dt <- data.table(
  ID = c(42, 43, 44),
  Stage_1 = c(-6, 7, 4),
  Stage_2 = c(-15, 4, -8),
  Stage_3 = c(-20, 2, -5)
)

#    ID Stage_1 Stage_2 Stage_3
# 1: 42      -6     -15     -20 # <~~ row to be selected (> 0 negative values)
# 2: 43       7       4       2
# 3: 44       4      -8      -5 # <~~ row to be selected (> 0 negative values)

我想要的输出是:

dt2 <- data.table(
  ID = c(42, 44),
  Stage_1 = c(-6, 4),
  Stage_2 = c(-15, -8),
  Stage_3 = c(-20, -5)
)

#    ID Stage_1 Stage_2 Stage_3
# 1: 42      -6     -15     -20
# 2: 44       4      -8      -5

ID 44 例如,有两个负值,但我想包括主数据表中的所有行。基本上所有在 any 列中具有负值的行我想添加到包含所有信息的新数据表中。

我正在使用的实际数据集有大约 50 个阶段列,所以最有效的解决方案就是我所追求的。

dt[Stage_1 < 0 | Stage_2 < 0 | Stage_3 < 0]

#    ID Stage_1 Stage_2 Stage_3
# 1: 42      -6     -15     -20
# 2: 44       4      -8      -5

OP澄清后编辑:

有很多列:

# Find all the rows with at least one negative in each column
rowsDT <- dt[, lapply(.SD, function(x) which(x < 0)), .SDcols = -'ID']
# Reduce to a vector by applying union
rows <- Reduce(union, rowsDT)
# Extract from the main data.table
dt[rows]
dt <- data.table::data.table(
  ID = c(42, 43, 44),
  Stage_1 = c(-6, 7, 4),
  Stage_2 = c(-15, 4, -8),
  Stage_3 = c(-20, 2, -5)
)

dt
#>    ID Stage_1 Stage_2 Stage_3
#> 1: 42      -6     -15     -20
#> 2: 43       7       4       2
#> 3: 44       4      -8      -5
  • 具有 apply() 功能:
dt[apply(dt[, -'ID'], 1, min) < 0, ]
#>    ID Stage_1 Stage_2 Stage_3
#> 1: 42      -6     -15     -20
#> 2: 44       4      -8      -5
  • with rowMeans() 函数基于这样一个事实,即具有至少一个真值的布尔向量的平均值总是大于零(感谢@utubun):
dt[rowMeans(dt[, -'ID'] < 0) > 0, ]
#>    ID Stage_1 Stage_2 Stage_3
#> 1: 42      -6     -15     -20
#> 2: 44       4      -8      -5
  • 以及 fBasics 包的 rowMins() 功能:
dt[fBasics::rowMins(dt[, -'ID']) < 0, ]
#>    ID Stage_1 Stage_2 Stage_3
#> 1: 42      -6     -15     -20
#> 2: 44       4      -8      -5

# Created on 2021-02-19 by the reprex package (v0.3.0.9001)

(与Equivalent to rowMeans() for min()相关)

此致,

不知道是不是真的好风格,但是作为shorthand你可以用这个:

dt[ dt[, any(.SD < 0), by = ID][['V1']], ]

#    ID Stage_1 Stage_2 Stage_3
# 1: 42      -6     -15     -20
# 2: 44       4      -8      -5

¹但是,如果 ID 不是唯一的,它会产生意想不到的结果。

data.table 选项使用 sign + rowSums

> dt[, .SD[rowSums(sign(.SD)) < length(.SD)], ID]
   ID Stage_1 Stage_2 Stage_3
1: 42      -6     -15     -20
2: 44       4      -8      -5