2

我正在尝试执行查找以检测我的观察数据框中的异常值。查找数据框 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 方式来完成这个查找?请帮忙。

问候

ķ

4

2 回答 2

3

您正在比较df_obs$val并且df_ref$idR 警告您它们的长度不相等,并且它可能会做一些您不期望的事情,即它会回收较短的向量。

我会使用 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
于 2013-08-31T09:46:20.623 回答
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

输出是 a factor,如果你需要它 as numeric,你必须做as.numeric(as.character(...)).

于 2013-08-31T10:35:55.367 回答