根据其他值之间的值合并两个数据库

时间:2018-10-09 15:09:48

标签: r merge dplyr

我想使用一个数据框中的类别,然后根据相似的列将其应用于另一个(合并)。但是,合并需要考虑在两列之间找到的数据点范围。我下面有一个例子。

set.seed(123)  

df_1 <- tibble(
  x = c(0, 500, 1000, 1500, 2000),
  y = c(499, 999, 1499, 1999, 99999),
  desc = LETTERS[1:5]
)

    > df_1
# A tibble: 5 x 3
      x     y desc 
  <dbl> <dbl> <chr>
1     0   499 A    
2   500   999 B    
3  1000  1499 C    
4  1500  1999 D    
5  2000 99999 E 

df_2 <- tibble(
  code = sample(1:2500,5,F)
)

 >df_2
# A tibble: 5 x 1
       code
      <int>
    1   719
    2  1970
    3  1022
    4  2205
    5  2348

## desired output


df_2 %>% 
  mutate(desc = c('B', 'D', 'C', 'E', 'E'))
# A tibble: 5 x 2
   code desc 
  <int> <chr>
1   719 B    
2  1970 D    
3  1022 C    
4  2205 E    
5  2348 E  

我的第一个想法是拆分df_1并以某种方式合并,但我坚持如何处理xy中的值范围。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

这是一个在SQL中易于处理的问题,因此一种选择是通过以下查询使用sqldf包:

SELECT t2.code, COALESCE(t1.desc, '') AS desc
FROM df_2 t2
LEFT JOIN df_1 t1
    ON t2.code BETWEEN t1.x AND t1.y;

R代码:

library(sqldf)
sql <- paste0("SELECT t2.code, COALESCE(t1.desc, '') AS desc ",
              "FROM df_2 t2 LEFT JOIN df_1 t1 ON t2.code BETWEEN t1.x AND t1.y")
result <- sqldf(sql)

答案 1 :(得分:1)

library(tidyverse)

set.seed(123)  

df_1 <- tibble(
  x = c(0, 500, 1000, 1500, 2000),
  y = c(499, 999, 1499, 1999, 99999),
  desc = LETTERS[1:5]
)

df_2 <- tibble(
  code = sample(1:2500,5,F)
)


df_1 %>%
  mutate(code = map2(x, y, ~seq(.x, .y, 1))) %>%  # create a sequence of numbers with step = 1
  unnest() %>%                                    # unnest data
  inner_join(df_2, by="code") %>%                 # join df_2 
  select(-x, -y)                                  # remove columns

# # A tibble: 5 x 2
#   desc   code
#   <chr> <dbl>
# 1 B       719
# 2 C      1022
# 3 D      1970
# 4 E      2205
# 5 E      2348

答案 2 :(得分:0)

这似乎可行,但不是很整洁:

df_2 %>% mutate(v = with(df_1, desc[ findInterval(code, x) ]))

  code v
1  719 B
2 1970 D
3 1022 C
4 2205 E
5 2348 E

这仅使用x列,因此假设范围内没有间隔(y始终在下一个x之下)。