![](/img/trans.png)
[英]how to conditionally create new column based on the values of a column in one dataframe and the column header names of another dataframe in R
[英]Assigning 1 or 0 conditionally to a new column based on values from another dataframe in R
我有一个32,000个条目的data.frame
。 这是一个示例:
# 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
则我想在cplt_flag
输入值1
,否则为0
。
我有一个使用if-else
语句的代码,但对于32,000
个条目,它的运行速度非常慢。 另外,我一直在尝试使用函数和应用函数,但是无法使其正常工作。
我正在寻找一种有效的方法来完成此任务。
您的数据集实际上并没有任何可能会出现TRUE
情况的情况。但是,这是一个使用data.table v1.9.7当前开发版本中新的非等额联接功能的解决方案。 请参阅此处的安装说明。
require(data.table) #v1.9.7+
setDT(df2)
setDT(df1)[df2, cplt_flag := 1, on = .(MINEVENT <= source_id, MAXEVENT >= source_id)]
对于df2
每一行,在满足提供给on=
参数的条件的情况下,从df1
中提取匹配的行索引。 在这些行索引上, cplt_flag
更新为1
。
使用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的作用域规则 。 要在函数范围之外修改变量,请使用<<-
代替<-
。 请参阅此以获取解释,并注意有关使用<<-
的警告。
假设df1$cplt_flag
最初为全零,因为match.criterion
仅将匹配的行设置为1
。 也就是说,与source_id
每个值的标准都不匹配的df1
行将被保留。
使用foreach
而不是apply函数之一的另一个矢量化解决方案是:
require(foreach)
foreach(source.id = df2$source_id) %do% match.criterion(source.id, df1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.