在R中:当条件匹配时,用另一个数据帧的值替换数据帧列的值

时间:2015-07-01 22:36:12

标签: r dataframe

我有两个数据帧:

set.seed(343)
testDF <- data.frame(Score = sample(50, size=50, replace=TRUE), number = rep(letters[1:25],2), Rev = rep(0,50))
sourceDF <- data.frame(min = c(1,10,20,30,40), max = c(9, 19, 29, 39, 50), rev = 1:5)

对于testDF的每一行,其中testDF $得分在sourceDF $ min和sourceDF的sourceDF $ max之间,请将testDF $ Rev的值替换为相应的sourceDF $ rev。

我使用了两个for循环和一个if条件,但它是......慢(我的数据集接近100万行)。 我尝试使用findInterval但没有成功。

有更好/更有效的方法吗?

2 个答案:

答案 0 :(得分:5)

首先,请参阅我对如何改进您的问题并使其重现的评论。其次,这是一种可能的方法,使用data.table::foverlaps

快速重叠连接
library(data.table)
setkey(setDT(testDF)[, Score2 := Score], Score, Score2) # create bounds and key
setkey(setDT(sourceDF), min, max) # Key by min, max
indx <- foverlaps(sourceDF, testDF, nomatch = 0L, which = TRUE) # run foverlaps
testDF[indx$yid,  Rev := sourceDF[indx$xid, rev]] # Update in place by corresponding values

答案 1 :(得分:0)

感谢您的回答。我想我没有测试就过快地发布了这个例子。对我感到羞耻...... @David感谢指示我将进一步了解foverlaps函数(并将探索更多的数据表世界)。

我找到了一种非常有效并且速度很快的解决方法。由于我的范围数量有限(示例中为5),因此我只使用变量Score上的过滤函数(dplyr库)将tesdDF子集化为5个数据帧。

testDF1 <- filter(testDF, Score>=1 & Score <=9) ## First DF

然后,这只是在每个数据帧中分配Rev值的问题。

testDF1$Rev <- sourceDF$rev[1]

对于800k +行的旧循环,这在不到1秒的时间内比1h35mn跑了。