根据R中目标值的上下限连接两个数据帧

时间:2018-07-25 09:04:53

标签: r dataframe join match

我有两个数据帧,$.ajax({ url:"your url", type: "GET", beforeSend: function(xhr){ //xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); }, success: function(data) { console.log(data); var resp = JSON.parse(data); //call another ajax function here } }); df1。我想以某种方式 join ,将目标值从df2添加到df2df1df1通过列组和值关联。在df2中,我有一个特定的值,在df1中,我仅具有适用值的下限和上限。

我认为,如果我们看看df2df1,任务应该很清楚。

df2

使用嵌套的for和if循环,我可以执行此任务。但是我的原始数据要大得多,因此无法使用此循环。我确信可以为我的任务找到一个更简单的解决方案。有什么建议吗?

df1 <- data.frame(group = c("A","B","C","D"),
                  value = c(15, 0, 40, 70))

df2 <- data.frame(group = c("A","A","A","A",
                            "B","B","B","B",
                            "C","C","C","C",
                            "D","D","D","D"),
                  lower_limit = c(0, 25, 60, 91,
                                  0, 35, 70, 92,
                                  0, 45, 80, 93,
                                  0, 55, 90, 94),
                  upper_limit = c(25, 60, 91, 100, 
                                  35, 70, 92, 100, 
                                  45, 80, 93, 100, 
                                  55, 90, 94, 100),
                  target = c("AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4"))

2 个答案:

答案 0 :(得分:3)

不确定所需的结果。也许与sdqldf:

df1 <- data.frame(group = c("A","B","C","D"),
                  value = c(15, 0, 40, 70))

df2 <- data.frame(group = c("A","A","A","A",
                            "B","B","B","B",
                            "C","C","C","C",
                            "D","D","D","D"),
                  lower_limit = c(0, 25, 60, 91,
                                  0, 35, 70, 92,
                                  0, 45, 80, 93,
                                  0, 55, 90, 94),
                  upper_limit = c(25, 60, 91, 100, 
                                  35, 70, 92, 100, 
                                  45, 80, 93, 100, 
                                  55, 90, 94, 100),
                  target = c("AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4",
                             "AGE0", "AGE1", "AGE3", "AGE4"))

library(sqldf)
sqldf("select a.*, b.target
         from df1 a
         left join df2 b
           on a.`group` = b.`group`
             AND a.value >= b.lower_limit 
             AND a.value <= b.upper_limit")

# group value target
#1     A    15   AGE0
#2     B     0   AGE0
#3     C    40   AGE0
#4     D    70   AGE1

答案 1 :(得分:3)

data.table方法可能是

library(data.table)

setDT(df2)[setDT(df1), .(group, value, target), 
           on = .(lower_limit <= value, upper_limit >= value, group)]

给出

   group value target
1:     A    15   AGE0
2:     B     0   AGE0
3:     C    40   AGE0
4:     D    70   AGE1


示例数据

df1 <- structure(list(group = structure(1:4, .Label = c("A", "B", "C", 
"D"), class = "factor"), value = c(15, 0, 40, 70)), .Names = c("group", 
"value"), row.names = c(NA, -4L), class = "data.frame")

df2 <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c("A", "B", "C", 
"D"), class = "factor"), lower_limit = c(0, 25, 60, 91, 0, 35, 
70, 92, 0, 45, 80, 93, 0, 55, 90, 94), upper_limit = c(25, 60, 
91, 100, 35, 70, 92, 100, 45, 80, 93, 100, 55, 90, 94, 100), 
    target = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
    2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("AGE0", "AGE1", "AGE3", 
    "AGE4"), class = "factor")), .Names = c("group", "lower_limit", 
"upper_limit", "target"), row.names = c(NA, -16L), class = "data.frame")

更新:根据OP的要求dplyr解决方案是

library(dplyr)

df1 %>% 
  left_join(df2, by = "group") %>%
  filter(value >= lower_limit, value <= upper_limit) %>%
  select(group, value, target)

#  group value target
#1     A    15   AGE0
#2     B     0   AGE0
#3     C    40   AGE0
#4     D    70   AGE1