r - 根据 data.table 中特定列上的多个条件标记行
问题描述
我有一个 data.table,其中包含特定年份的变量“Performance”的多个列和一个名为“ExPerf”的列。我想创建一个名为 FLAG 的新列,它将根据以下两个条件指示标记为手动查看的行:
- 任何“性能”列都有负值
- “ExPerf”列与任何列的差异超过 50%。
一个类似于我的模拟 data.table:
library(data.table)
dt <- data.table(Id = c("N23", "N34", "N11", "N65", "N55", "N78", "N88"),
Name = c("ABCD", "ACBD", "ACCD", "ADBN", "ADDD", "DBCA", "CBDA"),
Type = c("T", "B", "B", "T", "T", "B", "B"),
Sold = c(500, 300, 350, 500, 350, 400, 450),
Bl = c(2000, 2100, 2000, 1500, 1890, 1900, 2000),
P_2016 = c(-200, 420, 800, 900, -10, 75, 400),
P_2017 = c(500, 300, -20, 700, 50, 80, 370),
P_2018 = c(1000, 400, 600, 800, 40, 500, 300),
EP_2019 = c(1500, 380, 500, 850, 30, 400, 350))
dt
Id Name Type Sold Baseline Perf_2016 Perf_2017 Perf_2018 ExpPerf_2019
N23 ABCD T 500 2000 -200 500 1000 1500
N34 ACBD B 300 2100 420 300 400 380
N11 ACCD B 350 2000 800 -20 600 500
N65 ADBN T 500 1500 900 700 800 850
N55 ADDD T 350 1890 -10 50 40 30
N78 DBCA B 400 1900 75 80 500 400
N88 CBDA B 450 2000 400 370 300 350
对于此 data.table,所需的输出将添加 FLAG 列,如下所示:
Id Name Type Sold Baseline Perf_2016 Perf_2017 Perf_2018 ExpPerf_2019 FLAG
1: N23 ABCD T 500 2000 -200 500 1000 1500 TRUE
2: N34 ACBD B 300 2100 420 300 400 380 FALSE
3: N11 ACCD B 350 2000 800 -20 600 500 TRUE
4: N65 ADBN T 500 1500 900 700 800 850 FALSE
5: N55 ADDD T 350 1890 -10 50 40 30 TRUE
6: N78 DBCA B 400 1900 75 80 500 400 TRUE
7: N88 CBDA B 450 2000 400 370 300 350 FALSE
解决方案
- 任何性能列都有负值
- 预期性能列与任何性能列的差异超过 50%。
换句话说,这些列有共同的最小和最大界限:
- 最小值为最大值(0,ExpPerf*0.5)
- 最大值为 ExpPerf*1.5
所以...
dt[, v := !Reduce(`&`,
lapply(.SD, between, pmax(0, ExpPerf_2019*0.5), ExpPerf_2019*1.5)
), .SDcols=grep("^Perf_", names(dt), value=TRUE)]
Id Name Type Sold Baseline Perf_2016 Perf_2017 Perf_2018 ExpPerf_2019 v
1: N23 ABCD T 500 2000 -200 500 1000 1500 TRUE
2: N34 ACBD B 300 2100 420 300 400 380 FALSE
3: N11 ACCD B 350 2000 800 -20 600 500 TRUE
4: N65 ADBN T 500 1500 900 700 800 850 FALSE
5: N55 ADDD T 350 1890 -10 50 40 30 TRUE
6: N78 DBCA B 400 1900 75 80 500 400 TRUE
7: N88 CBDA B 450 2000 400 370 300 350 FALSE
这个怎么运作:
between
检查列是否介于最小值和最大值之间lapply
将检查应用于每一列,返回一个列表Reduce
with&
检查所有列是否满足条件!
否定结果,因此我们确定至少一列不符合条件的情况
between
,&
并且!
是向量化的运算符,所以我们最终得到一个结果向量,每行一个。我可能会在 magrittr 中编写此序列,因此步骤更易于遵循:
library(magrittr)
dt[, v := .SD %>%
lapply(between, pmax(0, ExpPerf_2019*0.5), ExpPerf_2019*1.5) %>%
Reduce(f=`&`) %>%
not
, .SDcols=grep("^Perf_", names(dt), value=TRUE)]
not
是!
magrittr 为方便起见提供的重新标记。
.SD
j
是在 的部分内部操作的数据子集的特殊符号DT[i, j, by]
。在这种情况下,没有i
or by
,所以只有.SDcols
子集(选择感兴趣的列)。
评论
- 如果 OP 选择以长格式格式化数据,代码会更简单。
- 我的答案使用与 Gilean 相同的步骤,但是是矢量化的,而不是按行计算。
推荐阅读
- java - Spring Boot Admin 使用 HTTP 而不是 HTTPS Actuator Endpoints
- php - 如何克服 preg_match '偏移量高于主题长度'?
- r - 使用 r 中的日期将多个 rds 文件添加到一个文件中
- c# - '验证散列密码时不是有效的 Base64 字符串
- python - Kubernetes 部署连接被拒绝
- typescript - 抽象类作为类型的实现
- python - Tensorflow:以特定顺序在张量(shape=[batchsize, 2])中从张量(shape=[batchsize])重塑和交换元素
- php - PHP Codeigniter中foreach循环中的单选按钮值
- python - 是否可以调整宽度 wx.StaticBox?
- razor - Umbraco Razor 导航访问自定义字段