Объединение двух фреймов данных с использованием ближайшего меньшего значения в R

#r #loops #merge

#r #циклы #слияние

Вопрос:

Я извлек частичную информацию из двух фреймов данных, как показано ниже:

 df1 <- data.frame(sample=c(1, 2, 3, 4, 5),
                       RT=c(3.88, 4.52, 32.82, 15.71, 20.33),
                       Hit=c(2, 1, 7, 1, 5))
 

и

 df2 <- data.frame(rt_stand=c(4.5, 8.5, 15.8, 23.2, 35.0),
                       n_carb=c(10, 11, 12, 13, 14),
                       below=c(5.5, 6.8, 8.2, 10.0, 12.3))
 

Я бы хотел, чтобы строки из df2 соединялись со строками df1 на основе ближайшего, но меньшего значения.

Выводом будет фрейм данных как таковой:

пример RT Удар rt_stand n_carb ниже
1 3.88 2 NA NA NA
2 4.52 1 4.5 10 5.5
3 32.82 7 23.2 13 10.0
4 15.71 1 8.5 11 6.8
5 20.33 5 15.8 12 8.2

Выше приведен небольшой воспроизводимый пример. Я считаю, что для работы со всем набором данных мне нужно будет создать цикл, который связывает / объединяет строки df2 с df1 на основе функции, которая находит минимальное, но меньшее число.

Любая помощь будет с благодарностью принята.

Комментарии:

1. Ближайшее, но меньшее значение какой переменной? Вы сравниваете RT of df1 с rt_stand of df2 ?

2. Скользящее соединение? Я не слишком понимаю логику, которую вы ожидаете: library(data.table); setDT(df1); setDT(df2); df2[df1, on="rt_stand==RT", roll=TRUE]

Ответ №1:

Вы можете использовать fuzzyjoin package для хранения строк, где RT больше, чем rt_stand и для каждого sample сохранить ближайшее значение.

 library(dplyr)

fuzzyjoin::fuzzy_inner_join(df1, df2, by = c('RT' = 'rt_stand'), 
                            match_fun = `>`) %>%
  arrange(sample, rt_stand) %>%
  group_by(sample) %>%
  slice(n()) %>% 
  ungroup -> result

result
# A tibble: 4 x 6
#  sample    RT   Hit rt_stand n_carb below
#   <dbl> <dbl> <dbl>    <dbl>  <dbl> <dbl>
#1      2  4.52     1      4.5     10   5.5
#2      3 32.8      7     23.2     13  10  
#3      4 15.7      1      8.5     11   6.8
#4      5 20.3      5     15.8     12   8.2
 

Обратите внимание, что вышеупомянутое result не имеет sample = 1 , поскольку нет RT значения, которое было бы больше, чем rt_stand для этого sample . Чтобы получить все sample значения, которые вы можете затем выполнить :

 df1 %>%
  filter(!sample %in% result$sample) %>%
  bind_rows(result)

#  sample    RT Hit rt_stand n_carb below
#1      1  3.88   2       NA     NA    NA
#2      2  4.52   1      4.5     10   5.5
#3      3 32.82   7     23.2     13  10.0
#4      4 15.71   1      8.5     11   6.8
#5      5 20.33   5     15.8     12   8.2
 

Комментарии:

1. Большое вам спасибо. Это отлично сработало, и fuzzyjoin чрезвычайно полезен!