我正在尝试执行查找以检测观察数据框中的异常值。查找数据帧df_ref相当小(约50行),观察数据帧约为200,000行。以下代码解释了示例数据和我的方法:
df_ref = data.frame(id = c(2, 7, 12), ref = c(15, 27, 32))
df_obs = data.frame(obs = rep(11, 4), val = c(3, 4, 7, 13))
查找基于以下逻辑(数据以df_ref编码。
if val >= 2 and val < 7 then ref = 15
if val >= 7 and val < 12 then ref = 27
if val >= 12 then ref = 32
我想在使用df_val中的val和df_ref的(id,ref)中基于上述逻辑确定的df_obs中添加列ref_val。
以下R函数正确执行查找
get_ref = function(x, df_ref) {
df_ref[df_ref$id == max(df_ref$id[x >= df_ref$id]), "val"]
}
当我在df_obs上使用此功能时,例如
mutate(df_obs, ref=get_ref(val, df_ref))
I get the following error:
obs val
1 11 3
2 11 4
3 11 7
4 11 13
Warning message:
In x >= df_ref$id :
longer object length is not a multiple of shorter object length
最终输出应该看起来像
df_obs
obs val ref
1 11 3 15
2 11 4 15
3 11 7 27
4 11 13 32
我在这里做错了什么?什么是更好的R-ish方式来完成这个查找?请帮忙。
问候
ķ
答案 0 :(得分:3)
您正在将df_obs$val
与df_ref$id
进行比较,并且R警告您它们长度不相等,它可能会做一些您不期望的事情,即它会回收较短的矢量。< / p>
我会使用data.tables进行滚动连接:
library(data.table)
dt_ref <- data.table(df_ref, key = "id")
dt_obs <- data.table(df_obs, key = "val")
dt_ref[dt_obs, roll = TRUE]
# id ref obs
# 1: 3 15 11
# 2: 4 15 11
# 3: 7 27 11
# 4: 13 32 11
答案 1 :(得分:1)
cut
可能会引起人们的兴趣(但是它的语法有时需要花些时间来熟悉它)。
cut(df_obs$val,
breaks = c(df_ref$id, Inf),
labels = df_ref$ref,
right = FALSE)
# [1] 15 15 27 32
# Levels: 15 27 32
输出为factor
,如果您需要numeric
,则必须执行as.numeric(as.character(...))
。