【发布时间】:2016-07-04 01:40:23
【问题描述】:
构建和评估包含各种条件的表格以针对数据集进行评估的最佳方法是什么?
例如,假设我想识别数据集中的无效行,如下所示:
library("data.table")
# notional example -- some observations are wrong, some missing
set.seed(1)
n = 100 # Number of customers.
# Also included are "non-customers" where values except cust_id should be NA.
cust <- data.table( cust_id = sample.int(n+1),
first_purch_dt =
c(sample(as.Date(c(1:n, NA), origin="2000-01-01"), n), NA),
last_purch_dt =
c(sample(as.Date(c(1:n, NA), origin="2000-04-01"), n), NA),
largest_purch_amt =
c(sample(c(50:100, NA), n, replace=TRUE), NA),
last_purch_amt =
c(sample(c(1:65,NA), n, replace=TRUE), NA)
)
setkey(cust, cust_id)
我要检查每个观察的错误是 last_purch_dt < first_purch_dt 或 largest_purch_amt < last_purch_amt 的任何出现,以及除 all 或 none 之外的任何缺失值。 (对于非购买者来说,所有缺失都可以。)
我只想在条件表中store the expressions as strings,而不是一系列硬编码的表达式(它变得非常长且难以记录/维护):
checks <- data.table( cond_id = c(1L:3L),
cond_txt = c("last_purch_dt < first_purch_dt",
"largest_purch_amt < last_purch_amt",
paste("( is.na(first_purch_dt) + is.na(last_purch_dt) +",
"is.na(largest_purch_amt) +",
"is.na(last_purch_amt) ) %% 4 != 0") # hacky XOR
),
cond_msg = c("Error: last purchase prior to first purchase.",
"Error: largest purchase less than last purchase.",
"Error: partial transaction record.")
)
我知道我可以循环遍历条件行和rbindlist 生成的子集,例如:
err_obs <-
rbindlist(
lapply(1:nrow(checks), function(i) {
err_set <- cust[eval( parse(text= checks[i,cond_txt]) ) , ]
cbind(err_set,
checks[i, .(err_id = rep.int(cond_id, times = nrow(err_set)),
err_msg = rep.int(cond_msg, times = nrow(err_set))
)]
)
} )
)
print(err_obs) # returns desired result
这似乎可以在评估中正确处理NAs。
当我说“什么是最好的方法”时,我是在问:
- 这是最好的方法,还是有比
rbindlist(lapply(...)更有效或更惯用的替代方法? - 我目前的方法是否存在缺陷?
- 是否可以将其写为合并或连接,例如
cust inner join checks on eval(checks.condition(cust.values)) == TRUE?
【问题讨论】:
标签: r data.table