我有一个data.frame
,有32,000个条目。这是一个样本:
# df1
MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
和另一个包含157个值的列表。这是一个样本:
# df2
source_id
211535
211535
211535
211536
211536
211536
我想阅读source_id
并测试该值是否介于MINEVENT
和MAXEVENT
之间。如果TRUE
,我想在1
中输入值cplt_flag
,否则0
。
我有一个使用if-else
语句的代码,但它对32,000
条目运行速度超慢。此外,我一直在尝试使用函数和应用函数,但无法使其工作。
我正在寻找一种有效的方法来完成这项工作。
答案 0 :(得分:2)
您的数据集实际上并不存在copy
场景的任何情况。但是这里是使用当前开发版本的data.table,v1中的新的非equi连接功能的解决方案。 9.7。请参阅安装说明here。
src
对于TRUE
中的每一行,提取匹配来自require(data.table) #v1.9.7+
setDT(df2)
setDT(df1)[df2, cplt_flag := 1, on = .(MINEVENT <= source_id, MAXEVENT >= source_id)]
的行索引,其中满足提供给df2
参数的条件。在这些行索引上,df1
使用on=
进行就地更新。
答案 1 :(得分:0)
使用match.criterion
函数和其中一个 apply 函数的替代解决方案应该比循环更快。我已经添加了一些额外的数据行来测试(不详尽但有说明性):
df1 <- read.table(text = "
MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
211535 211634 211535-211634 100 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680101 2680151 2680101-2680151 51 0", header = TRUE)
df2 <- read.table(text = "
source_id
211535
211535
211535
211536
211536
211536
2680051", header = TRUE)
match.criterion <- function(source.id, df1) {
matches <- which(df1$MINEVENT <= source.id & source.id <= df1$MAXEVENT)
df1$cplt_flag[matches] <<- 1
}
sapply(df2$source_id, match.criterion, df1 = df1)
print(df1)
## MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
##1 211535 211634 211535-211634 100 1
##2 2680001 2680051 2680001-2680051 51 1
##3 2680001 2680051 2680001-2680051 51 1
##4 2680001 2680051 2680001-2680051 51 1
##5 2680001 2680051 2680001-2680051 51 1
##6 2680001 2680051 2680001-2680051 51 1
##7 2680001 2680051 2680001-2680051 51 1
##8 2680101 2680151 2680101-2680151 51 0
注意:
这里的关键是理解R's scoping rule。要修改函数范围之外的变量,请使用<<-
而不是<-
。请参阅this以获取解释,并留意有关使用<<-
的警告。
这假定df1$cplt_flag
最初全为零,因为match.criterion
仅设置与1
匹配的行。也就是说,与df1
的每个值的标准不匹配的source_id
行将保持不变。
使用foreach
代替其中一个 apply 函数的另一个矢量化解决方案是:
require(foreach)
foreach(source.id = df2$source_id) %do% match.criterion(source.id, df1)