Объединить две базы данных на основе значений между другими значениями - PullRequest
0 голосов
/ 09 октября 2018

Я хотел бы использовать категорию из одного фрейма данных и применить ее к другой на основе аналогичного столбца (объединить).Но при слиянии необходимо учитывать диапазон точек данных, которые находятся между двумя столбцами.У меня есть пример ниже.

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 и каким-то образом объединить, но я застрял в том, как работать с диапазоном значений, найденных в x и y.Есть идеи?

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

Кажется, что это работает, но не очень tidyverse-ish:

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).

0 голосов
/ 09 октября 2018
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
0 голосов
/ 09 октября 2018

Эту проблему легко решить в 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 code:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...