如何在R /中执行复杂的多列匹配

use*_*193 4 r matching dataframe

我希望根据多个列上的条件匹配两个数据帧,但无法弄清楚如何.所以,如果有我的数据集:

df1 <- data.frame(lower=c(0,5,10,15,20), upper=c(4,9,14,19,24), x=c(12,45,67,89,10))
df2 <- data.frame(age=c(12, 14, 5, 2, 9, 19, 22, 18, 23))
Run Code Online (Sandbox Code Playgroud)

我希望将df2中的年龄与df1中的下限和上限之间的范围相匹配,目的是在df1中添加一个额外的列,其中包含df1中x的值,其中age位于上下之间.即我希望df2看起来像

age    x
12    67
14    67
 5    45
....etc. 
Run Code Online (Sandbox Code Playgroud)

我怎样才能实现这样的匹配?

Ten*_*bai 6

我会在选择中使用简单sapply和"anded"条件,df1$x如下所示:

df2$x <- sapply( df2$age, function(x) { df1$x[ x >= df1$lower & x <= df1$upper ] })
Run Code Online (Sandbox Code Playgroud)

这使:

> df2
  age  x
1  12 67
2  14 67
3   5 45
4   2 12
5   9 45
6  19 89
7  22 10
8  18 89
9  23 10
Run Code Online (Sandbox Code Playgroud)

例如,对于12岁,括号内的选择给出:

> 12 >= df1$lower & 12 <= df1$upper
[1] FALSE FALSE  TRUE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)

因此,df1$x通过此逻辑向量很容易,因为您的范围不重叠


ags*_*udy 6

使用foverlapsfrom data.table是您正在寻找的:

library(data.table)
setDT(df1)
setDT(df2)[,age2:=age]
setkey(df1,lower,upper)
foverlaps(df2, df1, by.x = names(df2),by.y=c("lower","upper"))[,list(age,x)]

#    age  x
# 1:  12 67
# 2:  14 67
# 3:   5 45
# 4:   2 12
# 5:   9 45
# 6:  19 89
# 7:  22 10
# 8:  18 89
# 9:  23 10
Run Code Online (Sandbox Code Playgroud)


Dav*_*urg 6

这是findInterval在熔化数据集上使用的另一种矢量化方法

library(data.table) 
df2$x <- melt(setDT(df1), "x")[order(value), x[findInterval(df2$age, value)]]
#   age  x
# 1  12 67
# 2  14 67
# 3   5 45
# 4   2 12
# 5   9 45
# 6  19 89
# 7  22 10
# 8  18 89
# 9  23 10
Run Code Online (Sandbox Code Playgroud)

这里的想法是

  • 首先,整理你的数据lower,upper并将在同一列中,x并将具有相应的值到新列,
  • 然后,根据这些范围(必要findInterval)对数据进行排序.
  • 最后,findIntervalx列中运行以找到正确的发生率

这是一个可能dplyr/ tidyr版本

library(tidyr)
library(dplyr)
df1 %>%
  gather(variable, value, -x) %>%
  arrange(value) %>%
  do(data.frame(x = .$x[findInterval(df2$age, .$value)])) %>%
  cbind(df2, .)
#   age  x
# 1  12 67
# 2  14 67
# 3   5 45
# 4   2 12
# 5   9 45
# 6  19 89
# 7  22 10
# 8  18 89
# 9  23 10
Run Code Online (Sandbox Code Playgroud)