Фильтрация строк данных на основе условий в разных данных с использованием dplyr - PullRequest
0 голосов
/ 25 октября 2018

У меня есть два кадра данных: df1 и df2 (см. Пример ниже).df1 содержит числовое начальное и конечное значение для каждого идентификатора символа.df2 содержит несколько событий на один символьный идентификатор, включая числовое значение времени.

library(dplyr)

df1 <- data_frame(id = c("A", "B"),
                  start = c(2, 3),
                  end = c(5, 9))

df2 <- data_frame(id = c(rep("A", 4), rep("B", 4)),
                  time = c(1, 3, 5, 8, 2, 3, 4, 10),
                  keep = c(FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE))

Я пытаюсь отфильтровать события в df2 с помощью dplyr на основе значения времени, равного или равного между начальным и конечным значениями дляидентификатор в df1.Таким образом, фильтр имеет вид «df2 $ time> = df1 $ start & df2 $ time <= df1 $ end», который должен выполняться для каждого идентификатора отдельно.Я добавил логический столбец «keep», чтобы показать, какие строки я хочу сохранить в df2. </p>

Как мне выполнить этот фильтр для каждого идентификатора?Предпочтительно с помощью dplyr.Это должно быть конечным результатом:

df2 %>%
  filter(keep == TRUE)

Любая помощь очень ценится!

Ответы [ 3 ]

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

Использование возможности неэквивалентного соединения :

# load the package and convert the dataframes to data.tables
library(data.table)
setDT(df1)
setDT(df2)

# non-equi join
df2[df1
    , on = .(id, time >= start, time <= end)
    , .(id, time = x.time)]

, что дает:

   id time
1:  A    3
2:  A    5
3:  B    3
4:  B    4

Что этоделает:

  • setDT() преобразовывает data.frame в data.table
  • Вы присоединяетесь df1 с df2.используя on = .(id, time >= start, time <= end), вы присоединяетесь к точному совпадению id, в то время как time должно быть больше или равно start от df1 и ниже или равно end от df1.
  • При выполнении неэквивалентного объединения вернет time -колонки из df1 (start и end) как time и time для случаев, когда выполняются условия соединения ( см. также здесь ).Чтобы понять, что я имею в виду, вы можете просто сделать df2[df1, on = .(id, time >= start, time <= end)].
  • . Используя .(id, time = x.time), вы получите нужные столбцы обратно.x.time относится к столбцу time из таблицы x-data.table, который равен df2.
.
0 голосов
/ 25 октября 2018

Это также работает

df2$start <- df1[match(df2$id, df1$id),"start"]
df2$end <- df1[match(df2$id, df1$id),"end"]
df2$keep <- df2$time>df2$start& df2$time<df2$end
result <- df2 %>%  filter(keep)
result
0 голосов
/ 25 октября 2018

Что-то вроде этого с dplyr:

  df1 %>% 
  left_join(df2) %>%                       #joining to have one dataset
  filter(time <= end, time >= start) %>%   # filter, you can use <, > in case
  select(-c(2,3))                          # remove useless column if necessary

# A tibble: 4 x 3
  id     time keep 
  <chr> <dbl> <lgl>
1 A         3 TRUE 
2 A         5 TRUE 
3 B         3 TRUE 
4 B         4 TRUE 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...